简体   繁体   中英

XSLT - how to change the value of any attribute whose value contains a given substring

Given the following 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' .

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.

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.)

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.

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.)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM