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

时间:2021-02-21 22:17:40

Given the following xml:

鉴于以下xml:

<inventory>
  <item name="..." sku="123"/>
  <item name="..." sku="not available"/>
  <catalog vendor="...">
      <product id="--not available--"/>
      <product id="345"/>
  </catalog
</inventory>

I would like to replace any attribute value (anywhere) that has "not available" in it with '000'.

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

I've tried different combinations in XSLT (it is not my forte), and I'm able to replace them when I put the specific XPath expression for each attribute. Unfortunately, the XML documents I might be dealing with (well formed mind you) might have different structure and attribute naming conventions.

我在XSLT中尝试了不同的组合(它不是我的强项),当我为每个属性设置特定的XPath表达式时,我可以替换它们。不幸的是,我可能正在处理的XML文档(格式良好的请记住)可能具有不同的结构和属性命名约定。

All that matter at is to scan specific attribute values (or value patterns) and replace them with a problem-specific default. I'm finding myself to the point of just hack a solution in Python (load doc, iterate the DOM and modify any attribute in any node that matches the criteria.)

所有的问题都是扫描特定的属性值(或值模式),并用问题特定的默认值替换它们。我发现自己只需在Python中破解一个解决方案(load doc,迭代DOM并修改任何符合条件的节点中的任何属性)。

But I would really like to learn the solution for this in XSLT (whether it is replacing attribute values that match a pattern, or just straight string comparisons), if one exists. Professional curiosity if you will.

但是我真的很想在XSLT中学习这个解决方案(如果存在的话,它是替换与模式匹配的属性值,还是直接进行字符串比较)。专业的好奇心。

Any help would be appreciated. Any recommendation on a source or book that explains these XLST/XPath intricacies would be great as well (I've only found very simple examples, nothing as arbitrary as this.)

如有任何帮助,我们将不胜感激。任何关于解释XLST/XPath复杂之处的源代码或书籍的建议都是非常好的(我只找到了非常简单的示例,没有什么比这更随意的了)。

1 个解决方案

#1


5  

Use

使用

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

plus

+

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

The second template is the identity transformation template that used alone copies everything level by level, node by node, always processing any attribute and any child nodes with matching templates. To that we add a template for attributes of any name (@*) where the content contains the not available string, we create an attribute of the same name and namespace but a different value 000. With the apply-templates in the identity transformation we have ensured that all attributes are processed and based on the match pattern and template priority any more specific templates perform a transformation, like changing the attribute value. We could add more templates as needed, for instance <xsl:template match="foo"/> to remove foo elements or <xsl:template match="bar"><foobar><xsl:apply-templates select="@* | node()"/></foobar></xsl:template> to transform bar elements to foobar elements.

第二个模板是标识转换模板,单独使用它逐层、逐个节点地复制所有内容,始终使用匹配的模板处理任何属性和任何子节点。为此,我们为包含不可用字符串的任何名称(@*)添加了一个模板,我们创建了一个名称和名称空间相同但值不同的属性000。通过标识转换中的应用模板,我们确保所有的属性都被处理,并且基于匹配模式和模板优先级,任何特定的模板都可以执行转换,比如更改属性值。我们可以根据需要添加更多模板,例如 来删除foo元素或 将bar元素转换为foobar元素。

#1


5  

Use

使用

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

plus

+

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

The second template is the identity transformation template that used alone copies everything level by level, node by node, always processing any attribute and any child nodes with matching templates. To that we add a template for attributes of any name (@*) where the content contains the not available string, we create an attribute of the same name and namespace but a different value 000. With the apply-templates in the identity transformation we have ensured that all attributes are processed and based on the match pattern and template priority any more specific templates perform a transformation, like changing the attribute value. We could add more templates as needed, for instance <xsl:template match="foo"/> to remove foo elements or <xsl:template match="bar"><foobar><xsl:apply-templates select="@* | node()"/></foobar></xsl:template> to transform bar elements to foobar elements.

第二个模板是标识转换模板,单独使用它逐层、逐个节点地复制所有内容,始终使用匹配的模板处理任何属性和任何子节点。为此,我们为包含不可用字符串的任何名称(@*)添加了一个模板,我们创建了一个名称和名称空间相同但值不同的属性000。通过标识转换中的应用模板,我们确保所有的属性都被处理,并且基于匹配模式和模板优先级,任何特定的模板都可以执行转换,比如更改属性值。我们可以根据需要添加更多模板,例如 来删除foo元素或 将bar元素转换为foobar元素。