0

I would like to change the content of a xml node. This is my source:

<content>
    <p>
    Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 
        <a href="http://www.example.com">
            <strong>http://www.example.com</strong>
        </a>
    At vero eos et accusam et justo duo dolores et ea rebum. 
   </p>
</content>

I would like to change the part inside the -Tag to the following result:

<content>
                    <p>
                        Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 
                        <a xlink:show="new" xlink:href="http://www.example.com" xlink:type="simple">
                            <strong>http://www.example.com</strong>
                        </a>
                        At vero eos et accusam et justo duo dolores et ea rebum. 
                    </p>
            </content>

So, basically I want to change "href" to xlik:href. Everything else should stay untouched, like the

-tag or the -Tag.

I was hoping I can do something like this:

    <xsl:for-each select=".../content">    

....
....

    <xsl:variable name="content">
            <xsl:copy-of select="content/node()" />
        </xsl:variable>

    <xsl:value-of select="replace($content, 'href', 'xlink:href')" />

....
....

    <xsl:for-each/>

But the result is, that all tags and attributes where gone:

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

                      http://www.example.com

                  At vero eos et accusam et justo duo dolores et ea >rebum.

What can I do to change only the href-Attribute?

LStrike
  • 1,598
  • 4
  • 26
  • 58

1 Answers1

2

First start off with the Identity Template

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

Then have a template that matches the a element, that creates a new a element with the attributes you need.

<xsl:template match="a">
  <a xlink:show="new" xlink:href="{@href}" xlink:type="simple">
    <xsl:apply-templates select="@*[name()!='href']|node()"/>
  </a>
</xsl:template>

This assumes you have the xlink namespace prefix defined in the XSLT.

Try this XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink">
  <xsl:output method="xml" indent="yes" />

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

  <xsl:template match="a">
    <a xlink:show="new" xlink:href="{@href}" xlink:type="simple">
      <xsl:apply-templates select="@*[name()!='href']|node()"/>
    </a>
  </xsl:template>
</xsl:stylesheet>

EDIT: In answer to your comment, you don't really need an xsl:for-each here, unless you are actually doing other transformations other than just changing the href attribute. The template approach is usually the way to go, and definitely worth learning out. But if it helps, here is a stylesheet that uses xsl:for-each that you may be able to adapt to suit your needs:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink">
  <xsl:output method="xml" indent="yes" />

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

  <xsl:template match="/">
    <xsl:for-each select="content">
    ...
    <content>
      <xsl:apply-templates select="@*|node()"/>
    </content>
    ...
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="a">
    <a xlink:show="new" xlink:href="{@href}" xlink:type="simple">
      <xsl:apply-templates select="@*[name()!='href']|node()"/>
    </a>
  </xsl:template>
</xsl:stylesheet>
Tim C
  • 70,053
  • 14
  • 74
  • 93
  • This looks very promising. But let me guess, I can't use this inside a xsl:for-each? – LStrike Jun 29 '16 at 12:23
  • 1
    You can do an `` within an `xsl:for-each` for example. It may help if you edited you question of your XSLT that contains the `xsl:for-each` you are trying to adapt. Thank you. – Tim C Jun 29 '16 at 12:30
  • Sorry, forget about that. I know that programming in templates seems to be much better, but I am not very used to that type of programming. – LStrike Jun 29 '16 at 12:41
  • It is worth making an effort to learn about templates in XSLT as they are really what XSLT is based on. If it helps though, I have amended my answer to show it using `xsl:for-each` (although it isn't really necessary if you are just changing one thing and nothing else) – Tim C Jun 29 '16 at 12:54
  • Awesome, thx a lot. I definitely will try to understand and learn how to use temlates. – LStrike Jun 29 '16 at 12:58