我想将输入XML映射到另一个XML,只需将输入中的值写入输出中的不同标记。
举个简单的例子,如下:
<root1>
<a1>valA<a1>
<b1>valB<b2>
</root1>
需要成为:
<root2>
<a2>valA</a2>
<b2>valB</b2>
</root2>
目前我的XSLT中有以下内容:
<xsl:apply-templates match="root1" />
<xsl:template match="root1">
<a2>
<xsl:value-of select="a1" />
</a2>
<b2>
<xsl:value-of select="b1" />
</b2>
</xsl:template>
问题是我的输出中不想要空标签。如果valA
和valB
为空,我会得到:
<root2>
<a2></a2>
<b2></b2>
<root2>
但我想省略空标签。我原本以为xsl:output
可能有一个属性,但是没有...我在SO上遇到过这个问题:XSLT: How to exclude empty elements from my result? - 但答案是间接的,它是指定第二个样式表以在第一次转换后去除空输出元素。
我需要使用一个样式表来完成此操作。当然,必须有一些更简洁的事情:
<xsl:if test="string-length(a1) != 0">
<a2>
<xsl:value-of select="a1" />
</a2>
</xsl:if>
甚至:
<xsl:template match="a1[string-length(.) != 0]">
<a2>
<xsl:value-of select="." />
</a2>
</xsl:template>
为每个元素重复??
答案 0 :(得分:1)
您的尝试在我看来很好,但不是测试字符串长度,而是许多人使用例如而是<xsl:template match="a1[normalize-space()]"><a2><xsl:value-of select="."/></a2></xsl:template>
。但是如果你需要检查一个元素是否为空,那么你需要一些谓词或测试表达式,没有你可以全局开启的设置。
答案 1 :(得分:0)
你能做的是拥有一个通用模板,匹配任何没有文字的'leaf'元素,然后忽略这样一个元素
<xsl:template match="*[not(*)][not(normalize-space())]" />
您可以将其与仅与a1
,b1
元素匹配的模板与任意条件相结合,这样您就可以转换为a2
,b2
当前
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root1">
<root2>
<xsl:apply-templates select="@*|node()"/>
</root2>
</xsl:template>
<xsl:template match="a1">
<a2>
<xsl:apply-templates select="@*|node()"/>
</a2>
</xsl:template>
<xsl:template match="b1">
<b2>
<xsl:apply-templates select="@*|node()"/>
</b2>
</xsl:template>
<xsl:template match="*[not(*)][not(normalize-space())]" />
</xsl:stylesheet>
请注意使用XSLT标识模板(在您的特定示例中不需要),因为您正在重命名所有元素,但如果您确实希望保留一些元素,则会使用它。