Chris Daniel has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,

I have some issues in XSLT conversion. I have xml with multple <PortDetails> tag.

<PortDetails> <PortType>A</PortType> <PortCode>USBAL</PortCode> <CutOffDate>2016-09-28</CutOffDate> <CutOffTime>12:00</CutOffTime> </PortDetails> <PortDetails> <PortType>L</PortType> <PortCode>USMIA</PortCode> <ETD>2016-10-13</ETD> </PortDetails>

Now I want to convert this as below:

<RoutingDetails> <StageQualifier>1</StageQualifier> (If PortType is A) <TransportMode>1</TransportMode> (If PortType is A) <TransportName>TRUCK</TransportName> (If PortType is A) <Origin>ESBCN</Origin> (If PortType is A) <ETD>2017-01-03 00:00:00 GMT</ETD> (If PortType is A) <Destination>ESBCN</Destination> (If PortType is L) <ETA>2017-01-20</ETA> (If PortType is L) </RoutingDetails>

Actually I need to merge the content of two PortDetails into one <RoutingDetails>

I have tried the below xsl

<xsl:for-each select="ScheduleDetails/PortDetails"> <xsl:choose> <xsl:when test="PortType[text()='A' or text()='L']"> <RoutingDetails> <xsl:if test="PortType ='A'"> <StageQualifier>1</StageQualifier> <TransportMode>6</TransportMode> <TransportName>NV PRECARRIAGE</TransportName> <Origin><xsl:value-of select="PortCode"/></Origin> <ETD><xsl:value-of select="CutOffDate"/></ETD> </xsl:if> <xsl:if test="PortType ='L'"> <Destination><xsl:value-of select="PortCode"/></Destination> <ETA><xsl:value-of select="ETD"/></ETA> </xsl:if> </RoutingDetails> </xsl:when> </xsl:choose> </xsl:for-each>

But output is not as per required one:

<RoutingDetails> <StageQualifier>1</StageQualifier> <TransportMode>6</TransportMode> <TransportName>NV PRECARRIAGE</TransportName> <Origin>USBAL</Origin> <ETD>2016-09-28</ETD> </RoutingDetails> <RoutingDetails> <Destination>USMIA</Destination> <ETA>2016-10-13</ETA> </RoutingDetails>

All I need to to have this data into single <RoutingDetails>. Please help on this.

Replies are listed 'Best First'.
Re: Conversion of Files Using XSLT
by choroba (Cardinal) on Dec 14, 2016 at 10:42 UTC
    I usually use XML::XSH2 to deal with XML (to get us back on the Perl track). I created an input file like this:

    and used the following xsh script to create a new file:

    my $in := open { $ARGV[0] } ; my $out := create RoutingDetails ; my $rd = $out/RoutingDetails ; my $pda = $in//PortDetails[PortType='A'] ; if $pda { set $rd/StageQualifier 1 ; set $rd/TransportMode 1 ; set $rd/TransportName 'NV PRECARRIAGE' ; insert element Origin into $rd ; cp $pda/PortCode/text() into $rd/Origin ; insert element ETD into $rd ; cp $pda/CutOffDate/text() into $rd/ETD ; } my $pdl = $in//PortDetails[PortType='L'] ; if $pdl { insert element Destination into $rd ; cp $pdl/PortCode/text() into $rd/Destination ; insert element ETA into $rd ; cp $pdl/ETD/text() into $rd/ETA ; } save :f 'output.xml' $out ;

    The output was different to what you stated, because it correctly used the values present in the input.

    <?xml version="1.0" encoding="utf-8"?> <RoutingDetails> <StageQualifier>1</StageQualifier> <TransportMode>1</TransportMode> <TransportName>NV PRECARRIAGE</TransportName> <Origin>USBAL</Origin> <ETD>2016-09-28</ETD> <Destination>USMIA</Destination> <ETA>2016-10-13</ETA> </RoutingDetails>

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Conversion of Files Using XSLT
by Corion (Patriarch) on Dec 14, 2016 at 09:23 UTC

    Where is your Perl code and how does it fail to do what you need to do?

    Are you using one of the XSLT modules?

    Does your XSL-Transform work with other XSLT interpreters?

      Hi Corion,

      I am doing that using xsltproc linux command as XML::XSLT is not supporting tag values match constraints.

      Command: xsltproc test.xsl TEST_FILE.XML

        Is xsltproc written in Perl?

        If not, you're highly unlikely to find support for xsltproc and XSLT on a forum that is geared towards learning Perl and its modules.

Re: Conversion of Files Using XSLT
by choroba (Cardinal) on Dec 14, 2016 at 09:23 UTC
    Your question is badly formatted. Please fix it (see Writeup Formatting Tips for tips and details).

    You didn't show the whole XML document. How do you know that the two PortDetails are related? Do they share a common parent or are they just adjacent?

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      Sorry for inconvenience.

      Nope they do not share the parent node.
      They are just the repeated collection of tags.

      The relation between two PortDetails is just a requirement.