我需要添加缺少的节点,然后排序包括添加的新节点
Posted
技术标签:
【中文标题】我需要添加缺少的节点,然后排序包括添加的新节点【英文标题】:I need to add missing node and then sort including the added new node 【发布时间】:2018-03-17 20:45:17 【问题描述】:我有一个输入 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 是强制性的)。现在,我需要添加这两个节点(作为空节点),然后我需要 sort 包括这两个节点。
排序顺序应为:名字、姓氏、电子邮件、性别、职业、手机、地址、地区、国家;
最终输出的 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>
有人可以帮我看看吗?
提前致谢。
【问题讨论】:
请展示您为编写 XSLT 所做的努力。这是一个简单的转换,可以通过学习 XSLT 基础知识来实现。 您好 Aniket,感谢您的回复。我已经包含了我尝试过的 XSLT。我得到的结果几乎就在附近,但是输出 xml 中出现了一些重复的数据。可以请你看一下吗。 您好 Aniket,当我在输入 xml 中没有这是对您的方法的一种改编,它使用模板创建新元素,并通过将各种应用模板包装到 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>
就足够了,但使用模式是一种可能的方式。
【讨论】:
嗨,马丁,感谢您的回复。当我在输入 xml 中没有person
元素本身,这应该可以避免您遇到的问题,它在xsl:if
测试中简单地创建新元素可能更容易。以上是关于我需要添加缺少的节点,然后排序包括添加的新节点的主要内容,如果未能解决你的问题,请参考以下文章