给出以下xml:
<inventory>
<item name="..." sku="123"/>
<item name="..." sku="not available"/>
<catalog vendor="...">
<product id="--not available--"/>
<product id="345"/>
</catalog
</inventory>
我想用'000'
替换其中“不可用”的任何属性值(任何地方)。
我在XSLT中尝试了不同的组合(这不是我的强项),当我为每个属性添加特定的XPath表达式时,我能够替换它们。不幸的是,我可能正在处理的XML文档(形成良好的思想)可能具有不同的结构和属性命名约定。
所有重要的是扫描特定属性值(或值模式)并将其替换为特定于问题的默认值。我发现自己只是在Python中破解了一个解决方案(加载doc,迭代DOM并修改符合条件的任何节点中的任何属性。)
但我真的想在XSLT中学习这个解决方案(无论是替换匹配模式的属性值,还是直接字符串比较),如果存在的话。如果你愿意,可以有专业的好奇心。
任何帮助将不胜感激。关于解释这些XLST / XPath复杂性的源或书的任何建议都会很棒(我只发现了非常简单的例子,没有任何像这样的任意。)
答案 0 :(得分:5)
使用
<xsl:template match="@*[contains(., 'not available')]">
<xsl:attribute name="{name()}" namespace="{namespace-uri()}">000</xsl:attribute>
</xsl:template>
加
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
第二个模板是单独使用的标识转换模板,逐个节点逐个复制所有属性,始终处理任何属性以及具有匹配模板的任何子节点。为此我们为任何名称(@*
)的属性添加模板,其中内容包含not available
字符串,我们创建具有相同名称和命名空间但具有不同值000
的属性。通过身份转换中的apply-templates,我们确保处理所有属性,并根据匹配模式和模板优先级,任何更具体的模板执行转换,例如更改属性值。我们可以根据需要添加更多模板,例如<xsl:template match="foo"/>
删除foo
元素,或<xsl:template match="bar"><foobar><xsl:apply-templates select="@* | node()"/></foobar></xsl:template>
将bar
元素转换为foobar
元素。