2

I have the following xml-file:

<Book description="for beginners" name="IT Book">
    <Available>yes</Available>
    <Info pages="500.</Info>
</Book>

I want it to look like this:

<Book description="for pros" name="IT Book">
    <Available>yes</Available>
    <Info pages="500.</Info>
</Book>

I looked up how to modify xml-documents properly on the internet. I found out that first of all I should declare a template for just copying everything:

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

However, I dont know how to write the template for the actual modification. Thanks for helping out a beginner.

EDIT: Here is my Stylesheet so far (as requested by uL1):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sig="http://www.w3.org/2000/09/xmldsig#">
    <xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>

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

    <xsl:template match="@description='for beginners'">
        <xsl:attribute name="{name()}">
            <xsl:text>for pros</xsl:text>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>
1
  • 1
    add another template that matches your target attribute <xsl:template match="Book/@description"><xsl:attribute name="description">for pros</xsl:attribute></xsl:template> Commented Nov 8, 2016 at 11:10

1 Answer 1

6

This question is already answered in many other threads. Eg. XSLT: How to change an attribute value during <xsl:copy>?

In your case, you need a template, which matches on your attribute description, besides the identity-copy template.

<xsl:template match="@description"> <!-- @ matches on attributes, possible to restrict! -->
  <xsl:attribute name="{name()}">   <!-- creates a new attribute with the same name -->
    <xsl:text>for pros</xsl:text>   <!-- variable statement to get your desired value -->
  </xsl:attribute>
</xsl:template>

EDIT 1 (further information cause of errors)

One complete, valid, runnable script would be:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

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

  <xsl:template match="@description[. = 'for beginners']">
    <xsl:attribute name="{name()}">
      <xsl:text>for pros</xsl:text>
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for the help. This seems to be the right direction. Unfortunately, i get an Error-message when trying to this in my xsl-stylesheet: xsl:attribute: Cannot add attributes to an element if children have been already added to the element.
Cannot add attributes to an element if children have been already added to the element occurs, when you create childnodes before you add the attribute to the context (e.g. current matched) node. changing the order might help. BUT there are several possibilities, eg. <xsl:apply-templates select="node()"/> before <xsl:apply-templates select="@*"/> will result in the error.
Isnt that what im allready doing at my copy template? : <xsl:copy> <xsl:apply-templates select="node() | @*"/> </xsl:copy>
I can't reproduce any failure with not seeing the complete xslt, you are executing. please try it on your own, or post your complete stylesheet in addition to your question via edit. I will update my answer to that as far as i can.
I added the requested stylesheet.
|

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.