Xml XSLT1将非唯一元素转换为网格的属性
我有一个具有这种结构的XML文件Xml XSLT1将非唯一元素转换为网格的属性,xml,xslt,xslt-1.0,xslt-grouping,Xml,Xslt,Xslt 1.0,Xslt Grouping,我有一个具有这种结构的XML文件 99 2. 4. 1. 6. 1. 2. 5. 3. 回答一个试图回答问题却没有付出任何努力的问题不是一个好主意。。。 但是,不管怎样,它在这里 XSL 1.0: , 给予: 例子: 参考资料: 以下是一种非常有效的方法: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xm
99
2.
4.
1.
6.
1.
2.
5.
3.
回答一个试图回答问题却没有付出任何努力的问题不是一个好主意。。。
但是,不管怎样,它在这里
XSL 1.0:
,
给予:
例子:
参考资料:
以下是一种非常有效的方法:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:key name="kDistinctChildren" match="level/*"
use="concat(generate-id(..), '+', name())" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="level">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates mode="group"
select="*[generate-id() =
generate-id(key('kDistinctChildren',
concat(generate-id(..), '+', name()))[1])]" />
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="group">
<xsl:attribute name="{name()}">
<xsl:apply-templates select="key('kDistinctChildren',
concat(generate-id(..), '+', name()))"
mode="joinWithCommas"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="*" mode="joinWithCommas">
<xsl:value-of select="concat(., substring(',', 1, position() != last()))"/>
</xsl:template>
</xsl:stylesheet>
在示例输入上运行时,输出为:
<levels>
<level id="0" qd="NE" gate="99" zone="2" laydown="4" />
<level id="0" qd="SE" gate="1" zone="6,5" laydown="1,2,3" />
</levels>
是否已知和详尽的id
、qd
、gate
、zone
和堆放?或者您需要从源XML动态获取属性列表吗?您已经尝试了什么?好的,这会起作用-但是这是一个好的解决方案吗?基本上,覆盖同一属性的次数与覆盖同名节点的次数相同。这样浪费CPU的能量会让大脑产生反抗……对于以下输入,这将无法正常工作:99 2 4 99 2 4
。谢谢@JLRishe,很好的回答!我又回到了我以前的版本(不管怎样效果更好)。我确实花了一些时间在这方面做了努力,但作为一个新手,我觉得这是一个垃圾,所以没有看到把它包括进去的意义。我愚蠢地认为XML很简单,所以我想我会使用它,但最终花费的时间是DB解决方案的3到4倍。至于xslt代码的正确性。。。。。我已经尝试了上述方法,除了VS2013崩溃和重新启动之外,我还遇到了一个错误“此文档已经有一个“文档元素节点”。@nickhoore不是问题,Nick,XSLT不是一个容易驯服的野兽!永远不要忽视自己编写代码的尝试,我更愿意帮助别人编写自己的代码,而不仅仅是给他们答案。祝你好运一个非常好的解决方案@NickHoare—这是一个很好的例子,说明使用XSLT 2.0()执行某些任务是多么容易。@NickHoare如果您回答了澄清请求,可能会找到一个更简单的答案。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:key name="kDistinctChildren" match="level/*"
use="concat(generate-id(..), '+', name())" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="level">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates mode="group"
select="*[generate-id() =
generate-id(key('kDistinctChildren',
concat(generate-id(..), '+', name()))[1])]" />
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="group">
<xsl:attribute name="{name()}">
<xsl:apply-templates select="key('kDistinctChildren',
concat(generate-id(..), '+', name()))"
mode="joinWithCommas"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="*" mode="joinWithCommas">
<xsl:value-of select="concat(., substring(',', 1, position() != last()))"/>
</xsl:template>
</xsl:stylesheet>
<levels>
<level id="0" qd="NE" gate="99" zone="2" laydown="4" />
<level id="0" qd="SE" gate="1" zone="6,5" laydown="1,2,3" />
</levels>