Xml XSLT复制全部并根据条件替换
我需要一个XSLT转换,将整个输入文档复制到输出文档,如果输入文档不包含某个元素,则插入一个具有默认值的特定元素 具体来说,我想转换这种通用形式的输入XMLXml XSLT复制全部并根据条件替换,xml,xslt,Xml,Xslt,我需要一个XSLT转换,将整个输入文档复制到输出文档,如果输入文档不包含某个元素,则插入一个具有默认值的特定元素 具体来说,我想转换这种通用形式的输入XML <Begin> <tag1>a</tag1> <tag2>b</tag2> </Begin> 到 x C 这是我当前的XSLT: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.
<Begin>
<tag1>a</tag1>
<tag2>b</tag2>
</Begin>
到
x
C
这是我当前的XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
它复制整个输入文档,但不提供默认的
元素。我不能在该样式表中的模板内使用
,因为它将在没有
的元素中插入
,并且我不能在模板后放置choose
,因为它无效。如何仅为
元素提供默认的
元素?如果没有tag1
并插入tag1
,则可以添加与Begin
匹配的模板。这里请注意,这适用于非常简单的示例,但是如果您有一个更复杂的案例,需要插入大量元素或多个元素,那么解决方案可能会变得更复杂
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Begin[not(tag1)]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<tag1>x</tag1>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
x
如果没有tag1
,则可以添加与Begin
匹配的模板,并插入tag1
。这里请注意,这适用于非常简单的示例,但是如果您有一个更复杂的案例,需要插入大量元素或多个元素,那么解决方案可能会变得更复杂
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Begin[not(tag1)]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<tag1>x</tag1>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
x
您不能将
元素放在模板之外,这是正确的。XSL通过转换输入文档的节点进行操作;您只能根据特定节点的转换方式(即通过模板)来表达转换的细节
此外,通过提供替代模板或select
表达式来表达替代方案通常比在模板内使用
的
等逻辑元素更为自然
在这种情况下,您需要考虑两种选择:
/Begin
元素有一个子元素tag1
/Begin
元素没有tag1
子元素Begin
元素,而不是标识转换,只要它适用
比如说,
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Begin[count(tag1) = 0]">
<xsl:copy>
<tag1>x</tag1>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
x
请注意添加的模板,它(仅)适用于没有子元素的
开始元素。它复制整个元素及其子节点,但也插入一个
如果您正确,则不能将
元素放在模板外部。XSL通过转换输入文档的节点进行操作;您只能根据特定节点的转换方式(即通过模板)来表达转换的细节
此外,通过提供替代模板或select
表达式来表达替代方案通常比在模板内使用
的
等逻辑元素更为自然
在这种情况下,您需要考虑两种选择:
输入文档的/Begin
元素有一个子元素tag1
输入文档的/Begin
元素没有tag1
子元素
在第一种情况下,您不需要做任何特殊的事情——您已经编写的身份转换将做正确的事情。因此,您只需要一个适当的模板来处理后一种选择。只要它比标识转换具有更高的优先级,它将用于Begin
元素,而不是标识转换,只要它适用
比如说,
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Begin[count(tag1) = 0]">
<xsl:copy>
<tag1>x</tag1>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
x
请注意添加的模板,它(仅)适用于没有子元素的开始元素。它复制整个元素及其子节点,但也插入一个
,您所描述的内容没有什么意义。为什么特别需要通过在应用模板
中选择节点()|@*
来执行此操作?除了是否存在/Begin/tag1
之外,转换的输出是否应该依赖于其他任何东西?从源文档“复制”的转换实际上是什么?我想特别使用node()|@*进行转换,因为我在过去的两个小时里一直在尝试这样做:):P无论如何,如果您有其他方法,我也很乐意看到。不,输出不应该依赖于除是否存在/Begin/tag1之外的任何东西。我想将源中的所有元素复制到目标。所以我想node()|@*是唯一的方法?不是吗?你前后矛盾。如果要将所有元素从输入复制到输出,则输出取决于输入中的所有元素。您之前说过,这只取决于/Begin/tag1
是否存在。我已经更新了问题,以反映您在评论和聊天中提供的澄清。如果我仍然误解了,那么请做出任何其他必要的改变。你所描述的毫无意义。为什么特别需要通过在应用模板
中选择节点()|@*
来执行此操作?除了是否存在/Begin/tag1
之外,转换的输出是否应该依赖于其他任何东西?从源文档“复制”的转换实际上是什么