Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT: change node inner text

Tags:

xslt

I need to transform the following xml doc:

<a>
  <b/>
  <c/>
   myText
</a>

into this:

<a>
  <b/>
  <c/>
   differentText
</a>

So, i wrote this XSLT document

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

  <xsl:template match="/a/text()">
    <a>
      <b/>
      <c/>
      differentText
    </a>
</xsl:template>
</xsl:stylesheet>

This way, i get the following result:

<?xml version="1.0" encoding="utf-8"?>
<a>
  <b /><c />
  differentText
</a>
<a>
  <b /><c />
  differentText
</a>
<a>
  <b /><c />
  differentText
</a>

The result appears repeated 3 times because 3 matches are being done.. Why? I could i fix it? Thanks

like image 452
Nabo Avatar asked May 22 '10 16:05

Nabo


2 Answers

Exclude the whtespace-only text nodes. Know and use the <xsl:strip-space> instruction.

This transformation:

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

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

 <xsl:template match="a/text()">
   <xsl:text>Diferent text</xsl:text>
 </xsl:template>
</xsl:stylesheet>

when applied to the provided XML document, produces the wanted correct result.

No need for complicated predicates in the match expression of the specific template!

We should be striving for the simplest, shortest, most elegant, most readable, most understandable solution that employs the full power of the language.

Chances are that such a solution will be most understood, most easy to implement and most likely to be optimized by any XSLT processor, resulting in a most efficient implementation.

like image 78
Dimitre Novatchev Avatar answered Jan 03 '23 15:01

Dimitre Novatchev


There are three matches, as highlighted by square brackets:

<a>[
  ]<b/>[
  ]<c/>[
   myText
]</a>

You want something like:

<xsl:template match="/a/text()[normalize-space() != '']">
like image 27
Tomalak Avatar answered Jan 03 '23 15:01

Tomalak