XSLT - 如何更改其值包含给定子字符串的任何属性的值

时间:2014-07-25 16:29:03

标签: xml xslt xpath

给出以下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复杂性的源或书的任何建议都会很棒(我只发现了非常简单的例子,没有任何像这样的任意。)

1 个答案:

答案 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元素。