XSLT/XML Copy value of node to node

Cali

I´m trying to copy the node content of one node to another. Basically the node content should be the same as in the first node except that the quotation marks in the second node should not be replaced.

I found some code and modified it but, it does only copy the first appearance of the first node content.

Here is the xslt code i have so far.

  <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:param name="pReplacement" select="/strings/string/de/text()"/>

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

    <xsl:template match="strings/string/es/text()">
     <xsl:value-of select="$pReplacement"/>
    </xsl:template>
</xsl:stylesheet>

The input XML is:

 <?xml version="1.0"?>
 <?xml-stylesheet href="test.xsl" type="text/xsl"?>
  <strings>
    <string name="cpu">
        <en>example1</en>
        <de>something1</de>
        <es>""</es>
    </string>
    <string name="gpu">
        <en>example2</en>
        <de>something2</de>
        <es>""</es>
    </string>
    <string name="mainboard">
        <en>example3</en>
        <de>something3</de>
        <es>""</es>
    </string>
</strings>

The wrong output is:

<?xml-stylesheet href="test.xsl" type="text/xsl"?><strings>
  <string name="cpu">
    <en>example1</en>
    <de>something1</de>
    <es>something1</es>
  </string>
  <string name="gpu">
    <en>example2</en>
    <de>something2</de>
    <es>something1</es>
  </string>
  <string name="mainboard">
    <en>example3</en>
    <de>something3</de>
    <es>something1</es>
  </string>
</strings>

The desired output should look like this.

<?xml-stylesheet href="test.xsl" type="text/xsl"?><strings>
  <string name="cpu">
    <en>example1</en>
    <de>something1</de>
    <es>"something1"</es>
  </string>
  <string name="gpu">
    <en>example2</en>
    <de>something2</de>
    <es>"something2"</es>
  </string>
  <string name="mainboard">
    <en>example3</en>
    <de>something3</de>
    <es>"something3"</es>
  </string>
</strings>

Maybe someone could help me to find a solution or point me in the right direction.

Many thanks in advance

Mathias Müller

Your approach does not work because the XPath expression

/strings/string/de/text()

has several results, three in this case. If you put them in a parameter like this:

<xsl:param name="pReplacement" select="/strings/string/de/text()"/>

then all three result nodes will be part of pReplacement. If you use a set of nodes in a place where only one node is expected, like in

<xsl:value-of select="$pReplacement"/>

then only the first node will be selected for this operation.

There is not much you have to change, just do away with the top-level parameter and replace the content of strings/string/es/text() with

<xsl:value-of select="../../de"/>

XSLT Stylesheet

<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="strings/string/es/text()">
     <xsl:value-of select="../../de"/>
    </xsl:template>

</xsl:stylesheet>

XML Output

<strings>
   <string name="cpu">
      <en>example1</en>
      <de>something1</de>
      <es>something1</es>
   </string>
   <string name="gpu">
      <en>example2</en>
      <de>something2</de>
      <es>something2</es>
   </string>
   <string name="mainboard">
      <en>example3</en>
      <de>something3</de>
      <es>something3</es>
   </string>
</strings>

Try this solution online here.


EDIT

If all es elements in your document should be affected by this change, you could also write the template as

<xsl:template match="es/text()">
  <xsl:value-of select="../preceding-sibling::de"/>
</xsl:template>

but this would require that there always is a de element as a child of the string element and that it is always before the es element. Finally, if there are several de elements that precede the es element, this would likely be a problem if you were using XSLT 2.0 since it would simply concatenate the string value of all preceding de elements.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related