简体   繁体   中英

Dynamically replace attribute or element values in XML using XSLT 2.0

I have an XML

<?xml version="1.0" encoding="utf-8"?>
<CATALOG>
    <PLANT COLOR="@DYNAMIC_COLOR@">
        <COMMON>Bloodroot</COMMON>
        <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>@DYNAMIC_PRICE@</PRICE>
        <AVAILABILITY>031599</AVAILABILITY>
    </PLANT>
    <PLANT COLOR="RED" TYPE="@DYNAMIC_TYPE@">
        <COMMON>Columbine</COMMON>
        <BOTANICAL>Aquilegia canadensis</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.37</PRICE>
        <AVAILABILITY>030699</AVAILABILITY>
    </PLANT>
</CATALOG>

I want to transform to

<?xml version="1.0" encoding="utf-8"?>
<CATALOG>
    <PLANT COLOR="RED">
        <COMMON>Bloodroot</COMMON>
        <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>10</PRICE>
        <AVAILABILITY>031599</AVAILABILITY>
    </PLANT>
    <PLANT COLOR="RED" TYPE="HERBS">
        <COMMON>Columbine</COMMON>
        <BOTANICAL>Aquilegia canadensis</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.37</PRICE>
        <AVAILABILITY>030699</AVAILABILITY>
    </PLANT>
</CATALOG>

Basically, i want to replace "@DYNAMIC_*@" attribute/element value with a predefined values. Please help!!! I can do with for each and exactly finding the values and replace it with the desired values. But i prefer to use apply template concept.

A neat solution for this kind of problem is to transform your skeleton XML document into a stylesheet. Write a transformation that converts it to:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" expand-text="yes">
  <xsl:param name="DYNAMIC_COLOR"/>
  <xsl:param name="DYNAMIC_TYPE"/>
  <xsl:template name="xsl:initial-template">
<CATALOG>
    <PLANT COLOR="{$DYNAMIC_COLOR}">
        <COMMON>Bloodroot</COMMON>
        <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>{$DYNAMIC_PRICE}</PRICE>
        <AVAILABILITY>031599</AVAILABILITY>
    </PLANT>
    <PLANT COLOR="RED" TYPE="{$DYNAMIC_TYPE}">
        <COMMON>Columbine</COMMON>
        <BOTANICAL>Aquilegia canadensis</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.37</PRICE>
        <AVAILABILITY>030699</AVAILABILITY>
    </PLANT>
</CATALOG>
  </xsl:template>
</xsl:stylesheet>

and then execute this stylesheet with entry point "xsl:initial-template" and with values for the parameters. I've used XSLT 3.0 value templates here to make it a bit easier; if you want to use XSLT 2.0 you can generate xsl:value-of instructions instead.

The basic logic for the conversion is

<xsl:stylesheet ...>
<xsl:namespace-alias stylesheet-prefix="z" result-prefix="xsl"/>
<xsl:variable name="params" select="distinct-values(
     (//@*|//text())[matches(., '^@.*@^')]!translate(., '@', ''))"/>

<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="/">
  <z:stylesheet version="3.0" expand-text="yes">
    <xsl:for-each select="$params">
      <z:param name="{.}"/>
    </xsl:for-each>
    <z:template name="xsl:initial-template">          
      <xsl:apply-templates/>
    </z:template>
  </z:stylesheet>
</xsl:template>

<xsl:template match="@*[matches(., '^@.*@$')]">
  <xsl:attribute name="{name()}" select="replace(., '^@(.*)@$', '{\$$1}')"/>
</xsl:template>

<xsl:template match="text()[matches(., '^@.*@$')]">
  <!-- 3.0 -->
  <!-- <xsl:value-of select="replace(., '^@(.*)@$', '{\$$1}')"/> -->
  <!-- 2.0 -->
  <z:value-of select="replace(., '^@(.*)@$', '\$$1'"/>
</xsl:template>

</xsl:stylesheet>

You may need to do a bit more work if there are attributes or text nodes that contain curly braces: these need to be doubled.

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