2
votes

I have an XML, something like this:

 <?xml version="1.0" encoding="UTF-8"?>
       <earth>
     <computer>
            <parts>
                <cpu>AMD;fast</cpu>
                <video>GF</video>
                <power>slow</power>
                ...others
            </parts>
            <owner>
             <name>Frank</name>
            <owner>
          </computer>

    <earth>

I want create xsl transform (xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"). My expected result only if cpu have sign ';' - power should be change to value after ';', if there will not be ';' result should no change

<earth>
 <computer>
        <parts>
            <cpu>AMD</cpu>
            <video>GF</video>
            <power>fast</power>
            ...others
        </parts>
        <owner>
          <name>Frank</name>
        <owner>
      </computer>
<earth>

Try to do something like this but no luck:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions"
    exclude-result-prefixes="fn">
    <xsl:output encoding="utf-8" method="xml" indent="yes" />
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="parts">
        <xsl:choose>
            <!-- try test if node name equals 'power' if equals them try make logic 
                here, this dont work-->
            <xsl:when test="name() = 'power'">
                <xsl:variable name="text" select="./cpu" />
                <xsl:variable name="sep" select="';'" />
                <xsl:variable name="powerTable" select="tokenize($text, $sep)" />
                <xsl:value-of select="$powerTable[1]" />
            </xsl:when>
            <!--if not 'power' copy node -->
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="@* | node()" />
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
1
"I have an XML stylesheet". May we know how does it looks like? Because the ones posted so far are just the XMLshar07
I edit my post, I have xml file and need create xsl to transform this file to new xml file with expected resultWait
Have you attempted to write the XSLT so far? If you have, please share it and explain which part is not working as expected or which part you have no idea how to implement. If you haven't, please read introductory tutorials on XSLT, and try to write one on your own first. Good luck!har07
Thx for reply, I create template for parts, try to test there if node name equals power, but this dont work. All others node should be copyWait

1 Answers

0
votes

I would use the following templates to accomplish this :

<xsl:template match="parts[contains(cpu,';')]/power">
    <power>
        <xsl:value-of select="../cpu/substring-after(.,';')"/>
    </power>
</xsl:template>

<xsl:template match="cpu[contains(.,';')]">
    <cpu>
        <xsl:value-of select="substring-before(.,';')"/>
    </cpu>
</xsl:template>

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

The first template matches power element that is direct child of parts (parts/power), where the parts has child element cpu that contains character ; (parts[contains(cpu,';')]). This template will output power element with the value from cpu element value, after character ;.

The second template, matches cpu element that contains character ;, and outputs cpu element with the initial value, before character ;.

The other template is just identity template which I assume you knew the purpose.