使用XSLT枚举具有相同名称的节点
我有很多XML文件,它们常常多次包含节点(每次包含不同的数据)。 例如:使用XSLT枚举具有相同名称的节点,xslt,muenchian-grouping,Xslt,Muenchian Grouping,我有很多XML文件,它们常常多次包含节点(每次包含不同的数据)。 例如: 达塔 数据库 数据中心 数据 达泰 达塔夫 达塔 所需的输出将是: <?xml version="1.0" encoding="UTF-8"?> <SomeName> <Node1> DataA </Node1> <Node2> DataB </Node2&
达塔
数据库
数据中心
数据
达泰
达塔夫
达塔
所需的输出将是:
<?xml version="1.0" encoding="UTF-8"?>
<SomeName>
<Node1>
DataA
</Node1>
<Node2>
DataB
</Node2>
<Node3>
DataC
</Node3>
<AnotherNode1>
DataD
</AnotherNode1>
<AnotherNode2>
DataE
</AnotherNode2>
<AnotherNode3>
DataF
</AnotherNode3>
<SingleNode>
DataG
</SingleNode>
</SomeName>
达塔
数据库
数据中心
数据
达泰
达塔夫
达塔
问题是,我没有一个包含所有重复节点名的列表,所以我需要XSLT遍历所有节点,只对存在多次的节点进行编号。可能吗
有没有人对如何做到这一点有好的想法
谢谢 您可以使用
count(前面的同级元素::*[name(.)=name(current())])
获取与上下文元素同名的前面同级元素的数量,并使用
创建与上下文元素同名的元素,并在其后面附加字母“n”。将这些事实结合起来应该可以让你达到你想要的效果。这里有一个完整的解决方案建议使用Muenchian方法进行分组,而不是基于计数(前面:*[someCondition])
进行分组,这是非常低效的--O(N^2)
此转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kElsByName"
match="/*/*" use="name()"/>
<xsl:template match="/*">
<SomeName>
<xsl:for-each select=
"*[generate-id()
=
generate-id(key('kElsByName', name())[1])
]
">
<xsl:variable name="vsameNamedNodes" select=
"key('kElsByName', name())"/>
<xsl:variable name="vNumSameNamedNodes" select=
"count($vsameNamedNodes)"/>
<xsl:for-each select="$vsameNamedNodes">
<xsl:element name="{concat(name(),
substring(position(),
1 div ($vNumSameNamedNodes > 1)
)
)
}">
<xsl:copy-of select="node()"/>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</SomeName>
</xsl:template>
</xsl:stylesheet>
<SomeName>
<Node>
DataA
</Node>
<Node>
DataB
</Node>
<Node>
DataC
</Node>
<AnotherNode>
DataD
</AnotherNode>
<AnotherNode>
DataE
</AnotherNode>
<AnotherNode>
DataF
</AnotherNode>
<SingleNode>
DataG
</SingleNode>
</SomeName>
<SomeName>
<Node1>
DataA
</Node1>
<Node2>
DataB
</Node2>
<Node3>
DataC
</Node3>
<AnotherNode1>
DataD
</AnotherNode1>
<AnotherNode2>
DataE
</AnotherNode2>
<AnotherNode3>
DataF
</AnotherNode3>
<SingleNode>
DataG
</SingleNode>
</SomeName>
应用于提供的XML文档时:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kElsByName"
match="/*/*" use="name()"/>
<xsl:template match="/*">
<SomeName>
<xsl:for-each select=
"*[generate-id()
=
generate-id(key('kElsByName', name())[1])
]
">
<xsl:variable name="vsameNamedNodes" select=
"key('kElsByName', name())"/>
<xsl:variable name="vNumSameNamedNodes" select=
"count($vsameNamedNodes)"/>
<xsl:for-each select="$vsameNamedNodes">
<xsl:element name="{concat(name(),
substring(position(),
1 div ($vNumSameNamedNodes > 1)
)
)
}">
<xsl:copy-of select="node()"/>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</SomeName>
</xsl:template>
</xsl:stylesheet>
<SomeName>
<Node>
DataA
</Node>
<Node>
DataB
</Node>
<Node>
DataC
</Node>
<AnotherNode>
DataD
</AnotherNode>
<AnotherNode>
DataE
</AnotherNode>
<AnotherNode>
DataF
</AnotherNode>
<SingleNode>
DataG
</SingleNode>
</SomeName>
<SomeName>
<Node1>
DataA
</Node1>
<Node2>
DataB
</Node2>
<Node3>
DataC
</Node3>
<AnotherNode1>
DataD
</AnotherNode1>
<AnotherNode2>
DataE
</AnotherNode2>
<AnotherNode3>
DataF
</AnotherNode3>
<SingleNode>
DataG
</SingleNode>
</SomeName>
达塔
数据库
数据中心
数据
达泰
达塔夫
达塔
产生想要的结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kElsByName"
match="/*/*" use="name()"/>
<xsl:template match="/*">
<SomeName>
<xsl:for-each select=
"*[generate-id()
=
generate-id(key('kElsByName', name())[1])
]
">
<xsl:variable name="vsameNamedNodes" select=
"key('kElsByName', name())"/>
<xsl:variable name="vNumSameNamedNodes" select=
"count($vsameNamedNodes)"/>
<xsl:for-each select="$vsameNamedNodes">
<xsl:element name="{concat(name(),
substring(position(),
1 div ($vNumSameNamedNodes > 1)
)
)
}">
<xsl:copy-of select="node()"/>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</SomeName>
</xsl:template>
</xsl:stylesheet>
<SomeName>
<Node>
DataA
</Node>
<Node>
DataB
</Node>
<Node>
DataC
</Node>
<AnotherNode>
DataD
</AnotherNode>
<AnotherNode>
DataE
</AnotherNode>
<AnotherNode>
DataF
</AnotherNode>
<SingleNode>
DataG
</SingleNode>
</SomeName>
<SomeName>
<Node1>
DataA
</Node1>
<Node2>
DataB
</Node2>
<Node3>
DataC
</Node3>
<AnotherNode1>
DataD
</AnotherNode1>
<AnotherNode2>
DataE
</AnotherNode2>
<AnotherNode3>
DataF
</AnotherNode3>
<SingleNode>
DataG
</SingleNode>
</SomeName>
达塔
数据库
数据中心
数据
达泰
达塔夫
达塔
使用计数(前面的兄弟姐妹::*[something])
效率很低(O(N^2))。请参阅我的答案以获得更有效的解决方案。好问题(+1)。请参阅我的答案,以获得一个完整且更高效的解决方案。哇。这也很好,很快!非常感谢XSLT!我所做的更改是将method=“xml”放在标题中以获得xml输出,但在其他方面,您的解决方案是完美的。再次感谢!实际上,是否有可能将其更改为不重命名唯一节点?XSLT基本上没有重命名SingleNode吗?谢谢@格林纳:是的,但是在评论中写新的解决方案很不方便。我可以编辑我的答案以包含最后一个要求。@Grinner:我编辑了我的答案。该解决方案现在正好生成您想要的输出。