Search code examples
xmlxsltxslt-1.0xslt-2.0

How to treat different same nodes in xslt


I have this :

    <?xml version="1.0" encoding="UTF-8"?>

    <ns0:envelope xmlns:ns0="http://xxx/xxx/envelope/1.0">
    <ns0:header>
    </ns0:header>
    <ns0:body>
        <ns1:sales xmlns:ns1="http://xxx/xxx/sales/1.0/" standardversion="1.1" guid="0">
            <ns1:itemMeta>
                <ns1:provider/>
                <ns1:documentModified>2018-10-05T11:41:09.344+02:00</ns1:documentModified>
                <ns1:documentVersion>1</ns1:documentVersion>
                <ns1:documentType>XML</ns1:documentType>
            </ns1:itemMeta>
            <ns1:contentSet>
                <ns1:inlineXML>
                    <group>
                        <ns2:ptv>
                            <ns2:id type="xxx">15566</ns2:id>
                            <ns2:info>
                                <ns2:type>xxx</ns2:type>
                                <ns2:name>xxx</ns2:name>
                        </ns2:ptv>
                        <ns2:ptv>
                            <ns2:id type="xxx">13444</ns2:id>
                            <ns2:info>
                                <ns2:type>yyy</ns2:type>
                                <ns2:name>yyy</ns2:name>
                        </ns2:ptv>
                        <ns2:ptv>
                            <ns2:id type="xxx">155525</ns2:id>
                            <ns2:info>
                                <ns2:type>xxx</ns2:type>
                                <ns2:name>xxx</ns2:name>
                        </ns2:ptv>
                    </group>
                </ns1:inlineXML>
            </ns1:contentSet>
        </ns1:salesItem>
    </ns0:body>
</ns0:envelope>

How can I read each "ptv" line separately within an xslt?

My xsl is something like this :

<xsl:template match="/">
        <xsl:element name="ptv">
            <xsl:attribute name="mode">
                <xsl:value-of select="/body/salesItem/contentSet/inlineXML/group/ptv/@mode"></xsl:value-of>
            </xsl:attribute>
            <xsl:attribute name="timestamp">
                <xsl:value-of select="/body/salesItem/contentSet/inlineXML/group/ptv/@timestamp"></xsl:value-of>
            </xsl:attribute>
            <xsl:apply-templates select="/body/salesItem/contentSet/inlineXML/group/ptv/*" mode="content" />
        </xsl:element>
    </xsl:template>

How to have all the objects "ptv" treated separtely ? (like a foreach ..)

The result at now is a one tag "ptv" and all the data of the "x" ptv inside ...

thx

edit : this is what I need as result. please let me know how can I do for this.

<?xml version="1.0" encoding="utf-8"?>


<ptv>
  <id type="xxx">15566</id>
<info> 
<type>xxx</type> 
<name>xxxx</name>
</info>
</ptv>

<ptv> 
<id type="xxx">15566</id>
<info> 
<type>xxx</type>
<name>xxxx</name>
</info>
</ptv> 

<ptv> 
<id type="xxx">15566</id>
<info> 
<type>xxx</type> 
<name>xxxx</name>
</info>
</ptv>

Solution

  • If you want to handle multiple elements, like your ptv the same, simply select them with an xsl:for-each, or better still, with a template...

    Try this XSLT

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:ns0="http://xxx/xxx/envelope/1.0"
        xmlns:ns1="http://xxx/xxx/sales/1.0/"
        xmlns:ns2="http://xxx/xxx/ptv/1.0/"
        exclude-result-prefixes="ns0 ns1 ns2"
        version="1.0">
    
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:strip-space elements="*" />
    
      <xsl:template match="/">
        <xsl:apply-templates select="/ns0:envelope/ns0:body/ns1:salesItem/ns1:contentSet/ns1:inlineXML/group/ns2:ptv" />
      </xsl:template>
    
      <xsl:template match="ns2:ptv">
        <ptv mode="{@mode}">
          <xsl:apply-templates mode="content"/>
        </ptv>
      </xsl:template>
    
      <xsl:template match="*" mode="content">
        <xsl:element name="{local-name()}">
          <xsl:copy select="@*" />
          <xsl:apply-templates mode="content" />
        </xsl:element>
      </xsl:template>  
    </xsl:stylesheet>
    

    Do note your XML is missing a namespace declaration, for ns2, so I made something up. Also note how the XSLT has to handle the namespaces in your XML.