6

For example I have a xml like

 <books>
   <book id="1">
     <title id="11" name="Basic XML"/>
     <price id="12" amount="500"/>
     <quantity id="13" number="10"/>
   </book>
 </books>

Can update the name of the book "Basic XML" to "Basic XSLT" or change any other attributes of any node using XSLT? If yes, can anyone give me some examples on how to do it?

Thanks in advance.

7
  • XSLT is used to transform XML files to a different format - sounds like overkill for what you want. Commented Mar 18, 2011 at 11:08
  • 1
    Good question, +1. See my answer for a complete, short and easy solution that is based on the most fundamental XSLT design pattern -- the use and overriding of the identity rule/template. Extensive explanation is also provided. Commented Mar 18, 2011 at 13:22
  • @sprenna: It's posible as @Dimitre's answer shows... But I agree with @Oded: For value replacement I would select the nodes with XPath and use the proper DOM method. Commented Mar 18, 2011 at 19:14
  • @Alejandro: EEEEEEEWWWWWW . . . Commented Mar 18, 2011 at 23:22
  • @Dimitre: Best approach really depends on what it's the meaning of "update". If that means "take an XML and serialize other XML document" from say... command line, I would go with XSLT. But if this is more general like those database questions or javascript DOM or any embedded environment where you or XSLT processor have to invoke a parser, perform the "update" and then serialize, I would go with XPath selection and DOM update. Of course, more complex process than value replacement will definitively require XSLT or XQuery. Commented Mar 19, 2011 at 1:45

2 Answers 2

8

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <my:reps>
  <repAttr name="name" value="Basic XSLT"/>
  <repAttr name="amount" value="300"/>
  <repAttr name="number" value="20"/>
 </my:reps>

 <xsl:strip-space elements="*"/>

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

 <xsl:template match=
   "@*[name()=document('')/*/my:reps/*/@name]">

   <xsl:attribute name="{name()}">
    <xsl:value-of select=
    "document('')/*/my:reps/*[@name=name(current())]/@value"/>
   </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<books>
    <book id="1">
        <title id="11" name="Basic XML"/>
        <price id="12" amount="500"/>
        <quantity id="13" number="10"/>
    </book>
</books>

produces the wanted, correct result:

<books>
   <book id="1">
      <title id="11" name="Basic XSLT"/>
      <price id="12" amount="300"/>
      <quantity id="13" number="20"/>
   </book>
</books>

Explanation:

  1. The identity rule/template copies every node "as-is".

  2. The identity template is overriden by a single template matching any attribute whose name can be found as value of one of the name attributes of a repAttr element that is specified in the my:reps element (parameters embeded in the XSLT stylesheet).

  3. In this case the attribute is re-created (not copied) with the same name and with the new value, specified in the corresponding repAttr element (its value attribute).

Sign up to request clarification or add additional context in comments.

1 Comment

great answer as always Dimitre
3

I cannot "update" the input Xml as XSLT is purely an output driven technology. It creates anew document and cannot modify the existing one.

You could make an almost identical copy but as @Oded comment points out XSLT may be overkill. The xsl would look something like (a modified identity transform)

<xsl:stylesheet version="1.0">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
   <xsl:template match="title/@Name">
     <!-- insert logic here to change the value as appropriate -->
   </xsl:template>
</xsl:stylesheet>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.