我有一个XML文件,如下所示:
<a>
......
<b>
<c>
<c1>some text</c1>
</c>
<d>
<d1>some more text</d1>
<d1>even more text</d1>
</d>
<e>
<e1>some more text</e1>
<e1>even more text</e1>
</e>
</b>
</a>
我想将元素<d>
和<e>
包装到<wrapper>
元素中,所以我可以使用以下内容:
<a>
......
<b>
<c>
<c1>some text</c1>
</c>
<wrapper>
<d>
<d1>some more text</d1>
<d1>even more text</d1>
</d>
<e>
<e1>some more text</e1>
<e1>even more text</e1>
<e2>even more</e2>
</e>
</wrapper>
</b>
......
</a>
我面临的一个问题(除了我是XSLT新手的事实)是<d>
和<e>
都是可选的。
我该怎么做?
答案 0 :(得分:2)
此转化:
<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()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b/*[self::d or self::e][1]">
<wrapper>
<xsl:apply-templates mode="copy" select=
". | following-sibling::*[self::d or self::e]"/>
</wrapper>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:copy>
<xsl:apply-templates mode="copy" select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b/*[self::d or self::e][position()>1]"/>
</xsl:stylesheet>
应用于提供的XML文档:
<a> ......
<b>
<c>
<c1>some text</c1>
</c>
<d>
<d1>some more text</d1>
<d1>even more text</d1>
</d>
<e>
<e1>some more text</e1>
<e1>even more text</e1>
</e>
</b>
</a>
产生想要的结果:
<a> ......
<b>
<c>
<c1>some text</c1>
</c>
<wrapper>
<d>
<d1>some more text</d1>
<d1>even more text</d1>
</d>
<e>
<e1>some more text</e1>
<e1>even more text</e1>
</e>
</wrapper>
</b>
</a>
注意:覆盖身份规则+模式。
答案 1 :(得分:2)
因为Dimitre通过模式解决方案发布组,我将通过相邻解决方案与组进行,以防万一:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()[1]|@*"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="*[self::d|self::e][1]">
<wrapper>
<xsl:call-template name="group"/>
</wrapper>
<xsl:apply-templates select="following-sibling::node()
[not(self::d|self::e)][1]"/>
</xsl:template>
<xsl:template match="node()" mode="group" name="group">
<xsl:copy>
<xsl:apply-templates select="node()[1]|@*"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]
[self::d|self::e]"
mode="group"/>
</xsl:template>
</xsl:stylesheet>
输出:
<a> ......
<b>
<c>
<c1>some text</c1>
</c>
<wrapper>
<d>
<d1>some more text</d1>
<d1>even more text</d1>
</d>
<e>
<e1>some more text</e1>
<e1>even more text</e1>
</e>
</wrapper>
</b>
</a>
编辑:更短的命名模板。
注意:这会在任何层次结构级别按原始顺序对下一个兄弟分组。这意味着它可能是几个wrapper
元素。
答案 2 :(得分:0)
难道你不能简单地围绕它进行if测试吗?
<wrapper>
<xsl:if test="/a/b/d">
<!-- write out the <d> node -->
</xsl:if>
<xsl:if test="/a/b/e">
<!-- write out the <e> node -->
</xsl:if>
</wrapper>