tags:

views:

63

answers:

2

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

+3  A: 

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() != '']">
Tomalak
As shown in my answer, no predicates are necessary in the match expression. :)
Dimitre Novatchev
@Dimitre: I know that. My answer provides the least possible change to the existing code. It's based on the assumption that the actual code is more complex and `<xsl:strip-space>` may cause side effects in other places.
Tomalak
@Tomalak: Supposing what the OP hasn't said often makes the solution suboptimal and more difficult to understand, even confusing. Going this way we may end up telling all we know about XSLT -- "just in case ..." :)
Dimitre Novatchev
@Dimitre: We're here to tell people what we know about XSLT anyway. And in this particular case, you did this even more than I did. ;) Don't get me wrong, your's *is* the more "by the book" solution. Mine is the one that requires changing just one line of code.
Tomalak
I enjoy this "meta-conversation" and suggest we have it more often.
Dimitre Novatchev
@All. I choosed the Dimitre's answer since when i have several templates, i just have to make 1 change. But i realy apreciated the Tomalak's answer and he was right when he said that my original code is more complex. When i'm posting questions i always simplify to help readers understand it faster. Now i sugest you take a look in this one. http://stackoverflow.com/questions/2899484/xslt-add-node-inner-text :)
Nabo
@nabo: No need to explain yourself regarding which answer you accepted. ;) But I nevertheless appreciate. When it comes to simplifying, take extra care not to over-simplify and thereby change the problem. I've seen that too often here, and it happens quite quickly. Sometimes posting the problem in all complexity helps you more, and even complex problems get attention here.
Tomalak
+3  A: 

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"&gt;
    <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.

Dimitre Novatchev
BTW, I do not consider `[normalize-space() != '']` a particularly complicated predicate. ;)
Tomalak
@Tomalak: 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. :)
Dimitre Novatchev