0

我有一个输入 XML,我需要使用 XSLT 2.0 对其进行转换。

这是我的输入 xml

<root>
         <person>
            <LastName>yyyyy</LastName>
            <FirstName>xxxx</FirstName>
            <profession>IT/xx</profession>
            <area>0000</area>
            <email>xxx.yyy@xxx.com</email>
            <Address>aaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeee</Address>
            <sex>male</sex>
         </person>
      </root>

我的输入 xml 缺少一些节点。例如(移动设备、国家/地区,根据 xsd 是强制性的)。现在,我需要添加这两个节点(作为空节点),然后我需要对这两个节点进行排序

排序顺序应为:FirstName,LastName,email,sex,professional,mobile,Address,area,country;

最终输出 xml 应该是:

<root>
         <person>
            <FirstName>xxxx</FirstName>
            <LastName>yyyyy</LastName>
            <email>xxx.yyy@xxx.com</email>
            <sex>male</sex>
            <profession>IT/xx</profession>
            <mobile/>
            <Address>aaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeee</Address>
            <area>0000</area>
            <country/>
         </person>
      </root>

我尝试使用以下 XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

    <xsl:param name="pOrderedNames" select="'FirstName,LastName,email,sex,profession,mobile,Address,area,country'"/>

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

    <xsl:template match="person[not(./country)]" mode="country">
        <xsl:element name="country" />
    </xsl:template>

    <xsl:template match="person[not(./mobile)]" mode="mobile">
        <xsl:element name="mobile" />
    </xsl:template>

    <xsl:template match="*" mode="sorter">
        <xsl:copy>
            <xsl:apply-templates>
                <xsl:sort data-type="number" select="string-length(substring-before($pOrderedNames,concat(',',name(),',')))"/>  
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="person">
        <xsl:copy>
            <xsl:apply-templates select="node()"/>
            <xsl:apply-templates  select="self::node()" mode="mobile"/>
            <xsl:apply-templates  select="self::node()" mode="country"/>
            <xsl:apply-templates  select="self::node()" mode="email"/>
            <xsl:apply-templates  select="self::node()" mode="sex"/>    
            <xsl:apply-templates select="self::*" mode="sorter"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

使用上面的 XSLT,它被转换如下:

<root>
   <person>
      <LastName>yyyyy</LastName>
      <FirstName>xxxx</FirstName>
      <profession>IT/xx</profession>
      <area>0000</area>
      <email>xxx.yyy@xxx.com</email>
      <Address>aaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeee</Address>
      <sex>male</sex>
      <mobile/>
      <country/>yyyyyxxxxIT/xx0000xxx.yyy@xxx.comaaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeeemaleyyyyyxxxxIT/xx0000xxx.yyy@xxx.comaaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeeemale<person>
         <FirstName>xxxx</FirstName>
         <LastName>yyyyy</LastName>
         <email>xxx.yyy@xxx.com</email>
         <sex>male</sex>
         <profession>IT/xx</profession>
         <Address>aaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeee</Address>
         <area>0000</area>
      </person>
   </person>
</root>

有人可以在这里帮我吗,拜托。

提前致谢。

4

1 回答 1

0

这是您的方法的改编,它使用模板创建新元素,并通过将各种应用模板包装到 a 中来对它们进行排序perform-sort

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

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

    <xsl:param name="pOrderedNames"
        select="'FirstName,LastName,email,sex,profession,mobile,Address,area,country'"/>
    <xsl:param name="pNameOrder" select="tokenize($pOrderedNames, ',')"/>

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

    <xsl:template match="person" mode="country">
        <country/>
    </xsl:template>

    <xsl:template match="person" mode="mobile">
        <mobile/>
    </xsl:template>

    <xsl:template match="person">
        <xsl:copy>
            <xsl:perform-sort>
                <xsl:sort select="index-of($pNameOrder, local-name())"/>
                <xsl:apply-templates select="*"/>
                <xsl:apply-templates select=".[not(country)]" mode="country"/>
                <xsl:apply-templates select=".[not(mobile)]" mode="mobile"/>
            </xsl:perform-sort>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

我不确定创建需要模板和模式的新元素,简单<xsl:if test="not(mobile)"><mobile/></xsl:if>就足够了,但使用模式是一种可能的方式。

于 2017-10-06T10:09:55.800 回答