【问题标题】:XSLT - how to change the value of any attribute whose value contains a given substringXSLT - 如何更改其值包含给定子字符串的任何属性的值
【发布时间】:2014-07-26 09:00:33
【问题描述】:

给定以下 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 中破解一个解决方案(加载文档、迭代 DOM 并修改任何节点中符合条件的任何属性。)

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

任何帮助将不胜感激。任何关于解释这些 XLST/XPath 错综复杂的资料或书籍的建议也很好(我只找到了非常简单的例子,没有像这样随意的。)

【问题讨论】:

  • XSLT 1 还是 2?在 2 中很容易,在 1 中这是不可能的,所以这很重要。 :)
  • @biziclop 在 XSLT 1.0 中一切皆有可能。
  • @biziclop 正则表达式不是必需的(正如我在写这篇文章时 Martin Honnen 已经展示过的那样)。
  • 那就需要改标题了。
  • @luis.espinal "XSLT - 如何根据当前值更改任何属性的值"?或者类似的东西。

标签: xml xslt xpath


【解决方案1】:

使用

<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。通过身份转换中的应用模板,我们确保处理所有属性,并根据匹配模式和模板优先级,任何更具体的模板执行转换,例如更改属性值。我们可以根据需要添加更多模板,例如&lt;xsl:template match="foo"/&gt; 删除foo 元素或&lt;xsl:template match="bar"&gt;&lt;foobar&gt;&lt;xsl:apply-templates select="@* | node()"/&gt;&lt;/foobar&gt;&lt;/xsl:template&gt;bar 元素转换为foobar 元素。

【讨论】:

  • 谢谢您,先生,成功了。我想知道你是否可以解释一下它是如何工作的。我认为我的比赛必须是"node() | @*"。顺序无关紧要,或者这是匹配任何节点上的任何属性的正确方法?谢谢。
  • @luis.espinal,我已经添加了一段来解释它。
  • 谢谢马丁,这很有帮助。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2020-09-24
  • 1970-01-01
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多