我的XML包含具有相同属性值但具有不同内容的兄弟节点。这发生在父级和子级别,如下所示:
<myxml>
<a myattr="valuetop1">
<b myattr="valuechild1">
<c>Stuff1</c>
<c>Stuff2</c>
</b>
</a>
<a myattr="valuetop1">
<b myattr="valuechild2">
<c>Stuff3</c>
</b>
</a>
<a myattr="valuetop1">
<b myattr="valuechild2">
<c>Stuff4</c>
</b>
</a>
<a myattr="valuetop1">
<b myattr="valuechild2">
<c>Stuff5</c>
<c>Stuff6</c>
</b>
</a>
<a myattr="valuetop2">
<b myattr="valuechild1">
<c>Stuff1</c>
</b>
</a>
<a myattr="valuetop2">
<b myattr="valuechild3">
<c>Stuff2</c>
</b>
</a>
<a myattr="valuetop2">
<b myattr="valuechild2">
<c>Stuff3</c>
<c>Stuff2</c>
</b>
</a>
<a myattr="valuetop2">
<b myattr="valuechild2">
<c>Stuff4</c>
</b>
</a>
</myxml>
如果存在具有相同属性值的节点存在于同一级别,我想将它们的内容组合在该节点的单个实例下。换句话说,我正在寻找一个整洁的层次结构:
<myxml>
<a myattr="valuetop1">
<b myattr="valuechild1">
<c>Stuff1</c>
<c>Stuff2</c>
</b>
<b myattr="valuechild2">
<c>Stuff3</c>
<c>Stuff4</c>
<c>Stuff5</c>
<c>Stuff6</c>
</b>
</a>
<a myattr="valuetop2">
<b myattr="valuechild1">
<c>Stuff1</c>
</b>
<b myattr="valuechild3">
<c>Stuff2</c>
</b>
<b myattr="valuechild2">
<c>Stuff3</c>
<c>Stuff2</c>
<c>Stuff4</c>
</b>
</a>
</myxml>
问题在于我不知道valuetopx或valuechildx的值是什么。我已经在这个问题上敲了几天,但是不能让我的大脑围绕它。
答案 0 :(得分:1)
正如评论中所提到的,您可以在XSLT 1.0中使用一种名为Muenchian Grouping的技术,但在您的情况下,您是在两个级别上进行的。
首先,对于父级,您可以像这样定义键
<xsl:key name="parent" match="a" use="@myattr" />
然后,对于孩子,您需要同时考虑父ID和子ID(在子ID可能具有不同父ID的情况下,因此将是不同的组)
<xsl:key name="child" match="b" use="concat(../@myattr, '|', @myattr)" />
然后,为了获得不同的父ID,你可以这样做....
<xsl:apply-templates select="a[generate-id() = generate-id(key('parent', @myattr)[1])]" />
在不同的父级中,为了获得不同的子元素,请执行此操作...
<xsl:apply-templates select="key('parent', @myattr)/b
[generate-id() = generate-id(key('child', concat(../@myattr, '|', @myattr))[1])]" />
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="parent" match="a" use="@myattr" />
<xsl:key name="child" match="b" use="concat(../@myattr, '|', @myattr)" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="myxml">
<xsl:copy>
<xsl:apply-templates select="a[generate-id() = generate-id(key('parent', @myattr)[1])]" />
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="key('parent', @myattr)/b[generate-id() = generate-id(key('child', concat(../@myattr, '|', @myattr))[1])]" />
</xsl:copy>
</xsl:template>
<xsl:template match="b">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="key('child', concat(../@myattr, '|', @myattr))/c" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>