XSLT: How to change an attribute value during ?

后端 未结 8 470
南旧
南旧 2020-11-29 01:14

I have an XML document, and I want to change the values for one of the attributes.

First I copied everything from input to output using:



        
相关标签:
8条回答
  • 2020-11-29 01:47

    This problem has a classical solution: Using and overriding the identity template is one of the most fundamental and powerful XSLT design patterns:

    <xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
        <xsl:param name="pNewType" select="'myNewType'"/>
    
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="property/@type">
            <xsl:attribute name="type">
                <xsl:value-of select="$pNewType"/>
            </xsl:attribute>
        </xsl:template>
    </xsl:stylesheet>
    

    When applied on this XML document:

    <t>
      <property>value1</property>
      <property type="old">value2</property>
    </t>
    

    the wanted result is produced:

    <t>
      <property>value1</property>
      <property type="myNewType">value2</property>
    </t>
    
    0 讨论(0)
  • 2020-11-29 01:48

    For the following XML:

    <?xml version="1.0" encoding="utf-8"?>
    <root>
        <property type="foo"/>
        <node id="1"/>
        <property type="bar">
            <sub-property/>
        </property>
    </root>
    

    I was able to get it to work with the following XSLT:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="//property">
            <xsl:copy>
                <xsl:attribute name="type">
                    <xsl:value-of select="@type"/>
                    <xsl:text>-added</xsl:text>
                </xsl:attribute>
                <xsl:copy-of select="child::*"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2020-11-29 01:53

    The top two answers will not work if there is a xmlns definition in the root element:

    <?xml version="1.0"?>
    <html xmlns="http://www.w3.org/1999/xhtml">
        <property type="old"/>
    </html>
    

    All of the solutions will not work for the above xml.

    The possible solution is like:

    <?xml version="1.0"?> 
    
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    
      <xsl:output omit-xml-declaration="yes" indent="yes"/>
      <xsl:template match="node()[local-name()='property']/@*[local-name()='type']">
          <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
                    some new value here
              </xsl:attribute>
      </xsl:template>
    
      <xsl:template match="@*|node()|comment()|processing-instruction()|text()">
          <xsl:copy>
              <xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()"/>
          </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2020-11-29 01:57

    Tested on a simple example, works fine:

    <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>
    <xsl:template match="@type[parent::property]">
      <xsl:attribute name="type">
        <xsl:value-of select="'your value here'"/>
      </xsl:attribute>
    </xsl:template>
    

    Edited to include Tomalak's suggestion.

    0 讨论(0)
  • 2020-11-29 02:01

    You need a template that will match your target attribute, and nothing else.

    <xsl:template match='XPath/@myAttr'>
      <xsl:attribute name='myAttr'>This is the value</xsl:attribute>
    </xsl:template>
    

    This is in addition to the "copy all" you already have (and is actually always present by default in XSLT). Having a more specific match it will be used in preference.

    0 讨论(0)
  • 2020-11-29 02:03

    I had a similar case where I wanted to delete one attribute from a simple node, and couldn't figure out what axis would let me read the attribute name. In the end, all I had to do was use

    @*[name(.)!='AttributeNameToDelete']

    0 讨论(0)
提交回复
热议问题