我有一个输入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,电子邮件,性别,专业,手机,地址,地区,国家/地区;
最终输出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>
请有人帮帮我。
先谢谢。
答案 0 :(得分:0)
以下是您的方法的改编,它使用模板创建新元素,并通过将各种apply-templates包装到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>
就足够了,但使用模式是可行的方法。