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

lui*_*nal 1 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>
Run Code Online (Sandbox Code Playgroud)

我想替换其中"不可用"的任何属性值(任何地方)'000'.

我在XSLT中尝试了不同的组合(这不是我的强项),当我为每个属性添加特定的XPath表达式时,我能够替换它们.不幸的是,我可能正在处理的XML文档(形成良好的思想)可能具有不同的结构和属性命名约定.

所有重要的是扫描特定属性值(或值模式)并将其替换为特定于问题的默认值.我发现自己只是在Python中破解了一个解决方案(加载文档,迭代DOM并修改符合条件的任何节点中的任何属性.)

但我真的想在XSLT中学习这个解决方案(无论是替换匹配模式的属性值,还是直接字符串比较),如果存在的话.如果你愿意,可以有专业的好奇心.

任何帮助,将不胜感激.关于解释这些XLST/XPath复杂性的源或书的任何建议都会很棒(我只发现了非常简单的例子,没有任何像这样的任意.)

Mar*_*nen 5

使用

<xsl:template match="@*[contains(., 'not available')]">
  <xsl:attribute name="{name()}" namespace="{namespace-uri()}">000</xsl:attribute>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

第二个模板是单独使用的标识转换模板,逐个节点逐个复制所有属性,始终处理任何属性以及具有匹配模板的任何子节点.为此,我们为任何name(@*)的属性添加模板,其中内容包含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元素.

  • @ luis.espinal,我添加了一段来解释它. (2认同)