2012-07-07 65 views
1

我在XML和XSLT分离并添加元素

的下面的查询XSLT空间是输入XML

<?xml version="1.0" encoding="UTF-8"?>  
<Employer> 
    <Employees> 
     <EmployeesDetails>van ind 26%</EmployeesDetails> 
    </Employees>  
    <Employees> 
     <EmployeesDetails>van ind</EmployeesDetails> 
    </Employees>  
</Employer> 

以上是我输入文件

下面是我输出文件

<?xml version="1.0" encoding="UTF-8"?> 
<Employer> 
    <Employees> 
     <Names>van</Names> 
     <Location>ind</Location>     
     <Weather>26</Weather> 
    </Employees> 
    <Employees> 
     <Names>van</Names> 
     <Location>ind</Location> 
     <Weather>100</Weather> 
    </Employees> 
</Employer> 

如何将以下XSLT应用于上述XML输入?

+0

你到目前为止尝试过什么?如果您能向我们展示您的需求,我们将很乐意为您提供帮助。 – Utkanos 2012-07-07 22:18:53

回答

0

你的问题在一些关键领域含糊不清。例如,你似乎声明如果一个<Employees>节点集不是有一个<weather>节点,它应该得到一个值为100%;那就是说,你的预期产出似乎并不一致。您希望的<Location>结果节点从大写转换为小写。此外,您的输出似乎完全忽略源XML中的第二个<Employees>节点集。

做一些假设,这里是一个使用EXSLT的XSLT 1.0解决方案。如果这不是你想要的,请更新你的问题,以更具体,我会尽量适应。

当该XSLT:

<?xml version="1.0"?> 
<xsl:stylesheet 
    xmlns:exsl="http://exslt.org/common" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    exclude-result-prefixes="exsl" 
    version="1.0"> 

    <xsl:output omit-xml-declaration="no" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Employees"> 
    <xsl:variable name="vNames"> 
     <xsl:call-template name="tokenize"> 
     <xsl:with-param name="text" select="Names/text()"/> 
     </xsl:call-template> 
    </xsl:variable> 
    <xsl:variable name="vLocations"> 
     <xsl:call-template name="tokenize"> 
     <xsl:with-param name="text" select="Location/text()"/> 
     </xsl:call-template> 
    </xsl:variable> 
    <xsl:apply-templates select="exsl:node-set($vNames)/token"> 
     <xsl:with-param name="pLocation" 
      select="exsl:node-set($vLocations)/token"/> 
     <xsl:with-param name="pWeather" select="Weather"/> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="token"> 
    <xsl:param name="pLocation"/> 
    <xsl:param name="pWeather"/> 
    <xsl:variable name="vPosition" select="position()"/> 
    <Employees> 
     <Names> 
     <xsl:value-of select="."/> 
     </Names> 
     <Location> 
     <xsl:value-of select="translate($pLocation[$vPosition], 
      'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/> 
     </Location> 
     <xsl:choose> 
     <xsl:when test="$pWeather != ''"> 
      <xsl:apply-templates select="$pWeather"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <Weather>100%</Weather> 
     </xsl:otherwise> 
     </xsl:choose> 
    </Employees> 
    </xsl:template> 

    <xsl:template name="tokenize"> 
    <xsl:param name="text"/> 
    <xsl:param name="delimiter" select="' '"/> 
    <xsl:choose> 
     <xsl:when test="contains($text,$delimiter)"> 
     <xsl:element name="token"> 
      <xsl:value-of select="substring-before($text,$delimiter)"/> 
     </xsl:element> 
     <xsl:call-template name="tokenize"> 
      <xsl:with-param name="text" 
       select="substring-after($text,$delimiter)"/> 
      <xsl:with-param name="delimiter" select="$delimiter"/> 
     </xsl:call-template> 
     </xsl:when> 
     <xsl:when test="$text"> 
     <xsl:element name="token"> 
      <xsl:value-of select="$text"/> 
     </xsl:element> 
     </xsl:when> 
    </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

...被施加到这个XML:(?)

<?xml version="1.0"?> 
<Employer> 
    <Employees> 
    <Names>vel bel sel tel mel</Names> 
    <Location>IND AUS ENG CAL JAP</Location> 
    <Weather>26%</Weather> 
    </Employees> 
    <Employees> 
    <Names>asd sadl asdsel tdddel dmdel</Names> 
    <Location>IND AUS ENG CAL JAP</Location> 
    </Employees> 
</Employer> 

...所期望的结果是产生的:

<?xml version="1.0" encoding="UTF-8"?> 
<Employer> 
    <Employees> 
    <Names>vel</Names> 
    <Location>ind</Location> 
    <Weather>26%</Weather> 
    </Employees> 
    <Employees> 
    <Names>bel</Names> 
    <Location>aus</Location> 
    <Weather>26%</Weather> 
    </Employees> 
    <Employees> 
    <Names>sel</Names> 
    <Location>eng</Location> 
    <Weather>26%</Weather> 
    </Employees> 
    <Employees> 
    <Names>tel</Names> 
    <Location>cal</Location> 
    <Weather>26%</Weather> 
    </Employees> 
    <Employees> 
    <Names>mel</Names> 
    <Location>jap</Location> 
    <Weather>26%</Weather> 
    </Employees> 
    <Employees> 
    <Names>asd</Names> 
    <Location>ind</Location> 
    <Weather>100%</Weather> 
    </Employees> 
    <Employees> 
    <Names>sadl</Names> 
    <Location>aus</Location> 
    <Weather>100%</Weather> 
    </Employees> 
    <Employees> 
    <Names>asdsel</Names> 
    <Location>eng</Location> 
    <Weather>100%</Weather> 
    </Employees> 
    <Employees> 
    <Names>tdddel</Names> 
    <Location>cal</Location> 
    <Weather>100%</Weather> 
    </Employees> 
    <Employees> 
    <Names>dmdel</Names> 
    <Location>jap</Location> 
    <Weather>100%</Weather> 
    </Employees> 
</Employer> 

说明:

  1. 第一个模板 - 在Identity Template - 将所有的元素和属性原样。
  2. 第二个模板与<Employee>元素匹配,运行一个特殊的tokenize模板,其作业是将空格分隔的字符串拆分为结果树片段。为了方便,这些片段被保存到变量中。
  3. 第三个模板匹配名为token的所有元素。这些由EXSLT生成,它将结果树片段转换为由<token>元素组成的节点集。对于其中的每一个,我们提取必要的元素值以创建<Names><Location>。该模板还包含确定<weather>元素需要哪个值所需的逻辑。
+0

如果输入XML的值为例如 25%该值必须在输出中显示25,如果输入XML中没有天气元素,则默认情况下它必须创建天气节点,值为100。 – maha 2012-07-08 05:26:50

1

I.此XSLT 2。0改造:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
exclude-result-prefixes="xs"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/*"> 
    <Employer> 
    <xsl:apply-templates/> 
    </Employer> 
</xsl:template> 

<xsl:template match="Employees"> 
    <xsl:variable name="vNames" select="tokenize(Names, ' ')"/> 
    <xsl:variable name="vLoc" select="tokenize(Location, ' ')"/> 
    <xsl:variable name="vWeather" 
     select="tokenize(translate(Weather, '%', ' '), ' ')"/> 
    <xsl:for-each select="$vNames"> 
    <xsl:variable name="vPos" select="position()" as="xs:integer"/> 
    <Employees> 
     <Names><xsl:sequence select="."/></Names> 
     <Location> 
     <xsl:sequence select="(lower-case($vLoc[$vPos]), 'Unknown')[1]"/> 
     </Location> 
     <Weather> 
     <xsl:sequence select="($vWeather[$vPos], 100)[1]"/> 
     </Weather> 
    </Employees> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

时所提供的XML文档应用:

<Employer> 
    <Employees> 
     <Names>vel bel sel tel mel</Names> 
     <Location>IND AUS ENG CAL JAP</Location> 
     <Weather>26%</Weather> 
    </Employees> 
    <Employees> 
     <Names>asd sadl asdsel tdddel dmdel</Names> 
     <Location>IND AUS ENG CAL JAP</Location> 
    </Employees> 
</Employer> 

产生想要的,正确的结果:

<Employer> 
    <Employees> 
     <Names>vel</Names> 
     <Location>ind</Location> 
     <Weather>26</Weather> 
    </Employees> 
    <Employees> 
     <Names>bel</Names> 
     <Location>aus</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>sel</Names> 
     <Location>eng</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>tel</Names> 
     <Location>cal</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>mel</Names> 
     <Location>jap</Location> 
     <Weather>100</Weather> 
    </Employees> 
     <Employees> 
     <Names>asd</Names> 
     <Location>ind</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>sadl</Names> 
     <Location>aus</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>asdsel</Names> 
     <Location>eng</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>tdddel</Names> 
     <Location>cal</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>dmdel</Names> 
     <Location>jap</Location> 
     <Weather>100</Weather> 
    </Employees> 
</Employer> 

请注意

我已经做了如下合理的假设:

  1. 你真正想要100,不100%

  2. 你想要所有的Employees处理 - 不仅是这个元素的第一次出现。

我还为缺失的位置添加了默认值,以防提供的位置数量少于提供的名称数量。


二, XSLT 1.0解决方案

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" 
xmlns:my="my:my" exclude-result-prefixes="ext my"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 
<my:defaults> 
    <L>Unknown</L> 
    <W>100</W> 
</my:defaults> 

<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/> 
<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/> 

<xsl:variable name="vDefaults" select="document('')/*/my:defaults"/> 

<xsl:template match="/*"> 
    <Employer> 
    <xsl:apply-templates/> 
    </Employer> 
</xsl:template> 

<xsl:template match="Employees"> 
    <xsl:variable name="vrtfNames"> 
    <xsl:apply-templates select="Names"/> 
    </xsl:variable> 
    <xsl:variable name="vNames" select="ext:node-set($vrtfNames)/*"/> 
    <xsl:variable name="vrtfLocs"> 
    <xsl:apply-templates select="Location"/> 
    </xsl:variable> 
    <xsl:variable name="vrtfWeather"> 
    <xsl:apply-templates select="Weather"/> 
    </xsl:variable> 

    <xsl:apply-templates select="$vNames"> 
    <xsl:with-param name="pLocs" select="ext:node-set($vrtfLocs)/*"/> 
    <xsl:with-param name="pWeather" select="ext:node-set($vrtfWeather)/*"/> 
    </xsl:apply-templates> 
</xsl:template> 

<xsl:template match="s" priority="3"> 
    <xsl:param name="pLocs"/> 
    <xsl:param name="pWeather"/> 

    <xsl:variable name="vPos" select="position()"/> 
    <Employees> 
    <Names><xsl:value-of select="."/></Names> 
    <Location> 
    <xsl:value-of select= 
     "translate($pLocs[position() = $vPos] 
        | $vDefaults[not($pLocs[position() = $vPos])]/L, 
        $vUpper, $vLower)"/> 
    </Location> 
    <Weather> 
    <xsl:value-of select= 
     "$pWeather[position() = $vPos] 
     | $vDefaults[not($pWeather[position() = $vPos])]/W"/> 
    </Weather> 
    </Employees> 
</xsl:template> 

<xsl:template match="Weather"> 
    <xsl:call-template name="tokenize"> 
    <xsl:with-param name="pText" select="translate(., '%', ' ')"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template match="Employees/*/text()" name="tokenize"> 
    <xsl:param name="pText" select="."/> 

    <xsl:variable name="vText" select="normalize-space($pText)"/> 
    <xsl:if test="$vText"> 
    <s> 
    <xsl:value-of select="substring-before(concat($vText, ' '), ' ')"/> 
    </s> 

    <xsl:call-template name="tokenize"> 
    <xsl:with-param name="pText" select="substring-after($vText, ' ')"/> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

当这种变换所提供的XML文档(以上)应用,再次同想,正确的结果产生

<Employer> 
    <Employees> 
     <Names>vel</Names> 
     <Location>ind</Location> 
     <Weather>26</Weather> 
    </Employees> 
    <Employees> 
     <Names>bel</Names> 
     <Location>aus</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>sel</Names> 
     <Location>eng</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>tel</Names> 
     <Location>cal</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>mel</Names> 
     <Location>jap</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>asd</Names> 
     <Location>ind</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>sadl</Names> 
     <Location>aus</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>asdsel</Names> 
     <Location>eng</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>tdddel</Names> 
     <Location>cal</Location> 
     <Weather>100</Weather> 
    </Employees> 
    <Employees> 
     <Names>dmdel</Names> 
     <Location>jap</Location> 
     <Weather>100</Weather> 
    </Employees> 
</Employer> 

请注意

  1. 基本上与XSLT 2.0 transforma中的逻辑相同重刑已落实。

  2. 作为XPath 1.0中不具有tokenizelower-case()功能和有是在XPath 1.0数据模型没有序列的概念,这些正在使用的标记化的模板实现(分别),使用translate()功能转换为小写,并使用包含天气和位置的默认值的元素。