xml - XSLT 转换合并值
问题描述
我有一个格式如下的 XML 输入文档:
<Label>
<Person>
<Hash>12345</Hash>
<Id>123123</Id>
<Firstname>John</Firstname>
<Lastname>Doe</Lastname>
<Category>Business</Category>
</Person>
<Person>
<Hash>12345</Hash>
<Id>456789<Id>
<Fistname>John</Firstname>
<Lastname>Doe</Lastname>
<Category>Information</Category>
</Person>
</Label>
我想合并 Person 中的所有子节点,这会产生以下输出文档:
<Label>
<Person>
<Hash>12345</Hash>
<Id>123123, 456789</Id>
<Firstname>John</Firstname>
<Lastname>Doe</Lastname>
<Category>Business, Information</Category>
<Person>
</Label>
所以实际上将 Person 中的所有节点合并为一个。最好将相同的值合并为一个值,但这不是必须的。因此,以下转换也是可以接受的:
<Label>
<Person>
<Hash>12345, 12345</Hash>
<Id>123123, 456789</Id>
<Firstname>John, John</Firstname>
<Lastname>Doe, Doe</Lastname>
<Category>Business, Information</Category>
<Person>
</Label>
任何关于如何实现这一点的建议都非常受欢迎!
最好在 xslt 1.0 中进行转换
解决方案
为了使查找字段值稍微简单一些,您可以定义一个键。
<xsl:key name="field" match="Person/*" use="local-name()" />
然后,您只需要选择第一个Person
元素的子节点,并为每个子节点使用键来键值...
<xsl:for-each select="key('field', local-name())">
<xsl:if test="position() > 1">, </xsl:if>
<xsl:value-of select="." />
</xsl:for-each>
试试这个 XSLT,它将重复项留在
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="field" match="Person/*" use="local-name()" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Person[1]/*">
<xsl:copy>
<xsl:for-each select="key('field', local-name())">
<xsl:if test="position() > 1">, </xsl:if>
<xsl:value-of select="." />
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="Person[position() > 1]" />
</xsl:stylesheet>
如果您确实想删除重复项,则需要使用 Muenchian Grouping。这意味着声明第二个密钥
<xsl:key name="fieldAndValue" match="Person/*" use="concat(local-name(), ':', .)" />
要获得不同的值,请更改xsl:for-each
如下:
<xsl:for-each select="key('field', local-name())[generate-id() = generate-id(key('fieldAndValue', concat(local-name(), ':', .))[1])]">
也试试这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="field" match="Person/*" use="local-name()" />
<xsl:key name="fieldAndValue" match="Person/*" use="concat(local-name(), ':', .)" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Person[1]/*">
<xsl:copy>
<xsl:for-each select="key('field', local-name())[generate-id() = generate-id(key('fieldAndValue', concat(local-name(), ':', .))[1])]">
<xsl:if test="position() > 1">, </xsl:if>
<xsl:value-of select="." />
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="Person[position() > 1]" />
</xsl:stylesheet>
当然,如果您可以使用 XSLT 2.0,您可以更简单...
<xsl:template match="Person[1]/*">
<xsl:copy>
<xsl:value-of select="distinct-values(key('field', local-name()))" separator=", " />
</xsl:copy>
</xsl:template>
编辑:如果您不能使用xsl:key
,则将xsl:for-each
(在不删除重复项的第一个 XSLT 中)更改为此....
<xsl:for-each select="//Person/*[local-name() = local-name(current())]">
这将保留重复项。可以在没有密钥的情况下删除重复项,但可能比它的价值太麻烦......
推荐阅读
- asp.net - asp.net api 重定向外部 url
- java - 如何使用 Soot 结束 catch 块?
- android - Error While Adding library for CardView
- react-native - 意外的标识符。react-native run-android
- powershell - Invoke-Command 忽略脚本文件中的#requires
- c - 如何在 C 中的 switch 中使用格式说明符
- php - 重定向到特定的 URL?
- c++ - static_cast 复合体
复杂的 在 C++ 中 - flutter - 如何在颤动中使用拇指创建一个范围滑块作为png图像
- javascript - 如何从科尔多瓦项目中调用图书馆的主要活动