我有一个大约具有以下结构的XML,这里的相关特征是元素对“F”和“Child_Fs”的递归关系。 “Child_Fs”可以包含任意数量的“F”,“F”只能包含一个“Child_Fs”:
<A>
<B>
<F id="1">
<J/>
<K/>
<Child_Fs>
<F id="1.1">
<J/>
<K/>
<Child_Fs>
<F id="1.1.1">
<J/>
<K/>
<Child_Fs>
...
</Child_Fs>
</F>
<F id="1.1.2">
...
</F>
<F id="1.1.3">
...
</F>
<F id="1.1.4">
...
</F>
.
.
.
</Child_Fs>
</F>
<F id="1.2">
...
</F>
<F id="1.3">
...
</F>
<F id="1.4">
...
</F>
.
.
.
</Child_Fs>
</F>
<F id="2">
...
</F>
<F id="3">
...
</F>
<F id="4">
...
</F>
.
.
.
<G/>
<H/>
<I/>
</B>
<C/>
<D/>
<E/>
</A>
我的实际XML不包含ID,我只是在这个例子中写了它们用于ilustration目的。
因此,我希望在转换之后获得以下XML,其中所有“F”元素都是其对应的最高“F / Child_Fs”祖先的子元素。这意味着F元素的最大深度应该只有两个出现(F / Child_Fs / F / Childfs)。这里另一个重要的要求是保持所有数据(属性和文本包含)完整,它只是一个重定位操作:
<A>
<B>
<F id="1">
<J/>
<K/>
<Child_Fs>
<F id="1.1">
<J/>
<K/>
<Child_Fs>
</Child_Fs>
</F>
<F id="1.1.1">
<J/>
<K/>
<Child_Fs>
</Child_Fs>
</F>
...
<F id="1.1.2">
...
</F>
<F id="1.1.3">
...
</F>
<F id="1.1.4">
...
</F>
.
.
.
<F id="1.2">
...
</F>
<F id="1.3">
...
</F>
<F id="1.4">
...
</F>
.
.
.
</Child_Fs>
</F>
<F id="2">
...
</F>
<F id="3">
...
</F>
<F id="4">
...
</F>
.
.
.
<G/>
<H/>
<I/>
</B>
<C/>
<D/>
<E/>
</A>
如果有人能给我一个暗示,我会非常感激。直到现在我还没有能够提出正确的XSL样式表。
非常感谢提前。
答案 0 :(得分:0)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Child_Fs[ancestor::Child_Fs]">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档时:
<A>
<B>
<F id="1">
<J/>
<K/>
<Child_Fs>
<F id="1.1">
<J/>
<K/>
<Child_Fs>
<F id="1.1.1">
<J/>
<K/>
<Child_Fs>
...
</Child_Fs>
</F>
<F id="1.1.2">
...
</F>
<F id="1.1.3">
...
</F>
<F id="1.1.4">
...
</F>
.
.
.
</Child_Fs>
</F>
<F id="1.2">
...
</F>
<F id="1.3">
...
</F>
<F id="1.4">
...
</F>
.
.
.
</Child_Fs>
</F>
<F id="2">
...
</F>
<F id="3">
...
</F>
<F id="4">
...
</F>
.
.
.
<G/>
<H/>
<I/>
</B>
<C/>
<D/>
<E/>
</A>
会产生想要的正确结果:
<A>
<B>
<F id="1">
<J/>
<K/>
<Child_Fs>
<F id="1.1">
<J/>
<K/>
<F id="1.1.1">
<J/>
<K/>
...
</F>
<F id="1.1.2">
...
</F>
<F id="1.1.3">
...
</F>
<F id="1.1.4">
...
</F>
.
.
.
</F>
<F id="1.2">
...
</F>
<F id="1.3">
...
</F>
<F id="1.4">
...
</F>
.
.
.
</Child_Fs>
</F>
<F id="2">
...
</F>
<F id="3">
...
</F>
<F id="4">
...
</F>
.
.
.
<G/>
<H/>
<I/>
</B>
<C/>
<D/>
<E/>
</A>
<强>解释强>:
正确使用和覆盖 identity rule 。
答案 1 :(得分:0)
只要您描述的结构保持不变,就可以使用如下所述的相当简单的算法。如果结构变得更加自由,那么它将成为一个更难的问题。
Child_Fs恰好有1个祖先F:
具有超过1个祖先F的Child_Fs:
d
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xi="http://www.w3.org/2001/XInclude"
exclude-result-prefixes="xsl xi">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Child_Fs[count(ancestor::F)=1]">
<!-- Child_F which is recipient of all Fs. -->
<xsl:copy>
<xsl:apply-templates select="@* | node() | //F" />
</xsl:copy>
</xsl:template>
<xsl:template match="Child_Fs[count(ancestor::F) > 1]">
<!-- Child_F which is donor of Fs. -->
<xsl:copy>
<xsl:apply-templates select="@* | node()[not(self::F)]" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>