Link to home
Start Free TrialLog in
Avatar of scurtis_1
scurtis_1

asked on

XSLT: Repeating tag needs to be transformed?

Hi,

We have the following XSL which looks for a tag called JobPackURL, takes a copy of the value from this tag, puts quotes round the copy and places the copy into a TemporaryItemDs structure. The original XML is retained with the new TemporaryItemDs structure being the only change:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
 
  <xsl:template match="/ | @* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
 
     <xsl:template match="TemporaryItemDs[last()]">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
         <xsl:for-each select="../FieldSupportInformation/JobPack">
              <TemporaryItemDs>
                 <TemporaryItemCode>JOBPCK</TemporaryItemCode>
                       <TemporaryItemValue>"<xsl:value-of select="JobPackURL" />"</TemporaryItemValue>
                   </TemporaryItemDs>
         </xsl:for-each>          
     </xsl:template>
</xsl:stylesheet>

We have now been told that the JobPackURL is a repeating tag and will appear as JobPackURL1, JobPackURL2, JobPackURL3 etc. So for each one we need to take the value and put it in quotes and add it to a new TemporaryItemDs structure.

Any examples showing how to do this woukd be very welcome!

Thanks
Scott
Avatar of anthonywjones66
anthonywjones66

Hello again,
 
        <xsl:for-each select="../FieldSupportInformation/*[substring(local-name(), 1, 7) =JobPack]">
              <TemporaryItemDs>
                 <TemporaryItemCode>JOBPCK</TemporaryItemCode>
                    <TemporaryItemValue>"<xsl:value-of select="JobPackURL" />"</TemporaryItemValue>
                </TemporaryItemDs>
         </xsl:for-each>          
 
How's this.

Anthony
oops,

="../FieldSupportInformation/*[substring(local-name(), 1, 7) = 'JobPack']">

Apostrophes missing
JobPackURL1, JobPackURL2, etc... right? not JobPack1, JobPack2....
Pretty close to what's above then:
<xsl:for-each select="../FieldSupportInformation/JobPack">
  <TemporaryItemDs>
    <TemporaryItemCode>JOBPCK</TemporaryItemCode>
    <TemporaryItemValue>"<xsl:value-of select="*[substring(local-name(), 1, 10) ='JobPackURL']" />"</TemporaryItemValue>
  </TemporaryItemDs>
</xsl:for-each>

Or you could even do <xsl:value-of select="*[substring-after(.,'JobPackURL')]"/>
Scott,

Having just read jkmyoung's comment I've re-read you question and I see we both haven't quite hit the nail on the head.  Now having read it a little more carefully are you saying you've got this:-

<JobPack>
   <JobPackURL1>x</JobPackURL1>
   <JobPackURL2>y</JobPackURL2>
</JobPack>

and you want something like:-

 <TemporaryItemCode>JOBPCK</TemporaryItemCode>
   <TemporaryItemValue>"x"</TemporaryItemValue>
   <TemporaryItemValue>"y"</TemporaryItemValue>
 </TemporaryItemDs>

??

Then you need:-

        <xsl:for-each select="../FieldSupportInformation/JobPack">
              <TemporaryItemDs>
                 <TemporaryItemCode>JOBPCK</TemporaryItemCode>
                    <xsl:for-each select="*[substring(local-name(),1,7) = 'JobPackURL']">
                      <TemporaryItemValue>"<xsl:value-of select="." />"</TemporaryItemValue>
                    </xsl:for-each>
                </TemporaryItemDs>
         </xsl:for-each>          
 
If JobPackURLn elements are the only children of JobPack then:-

       <xsl:for-each select="../FieldSupportInformation/JobPack">
              <TemporaryItemDs>
                 <TemporaryItemCode>JOBPCK</TemporaryItemCode>
                    <xsl:for-each select="*">
                      <TemporaryItemValue>"<xsl:value-of select="." />"</TemporaryItemValue>
                    </xsl:for-each>
                </TemporaryItemDs>
         </xsl:for-each>          
 
If you want the TemporyItemDs to repeat for each JobPackURLn found (which I'm guessing from a previous question asked by somelse about the same XML structure you do. :).

       <xsl:for-each select="../FieldSupportInformation/JobPack/*">
              <TemporaryItemDs>
                 <TemporaryItemCode>JOBPCK</TemporaryItemCode>
                      <TemporaryItemValue>"<xsl:value-of select="." />"</TemporaryItemValue>
                </TemporaryItemDs>
         </xsl:for-each>          

Finally if you need to TemporyItemDs to repeat but the JobPack may contain other elements that are not JobPackURLn then:-

     <xsl:for-each select="../FieldSupportInformation/JobPack/*[substring(local-name(),1,7) = 'JobPackURL']">
              <TemporaryItemDs>
                 <TemporaryItemCode>JOBPCK</TemporaryItemCode>
                      <TemporaryItemValue>"<xsl:value-of select="." />"</TemporaryItemValue>
                </TemporaryItemDs>
       </xsl:for-each>          


Take you pick.  :)

Anthony.



Hi Anthony,

You were correct in thinking it was the same problem. I will expand on what Scott has described above to give a more detailed/accurate description of the problem/requirement. The first soltuion you offered above worked correctly apart from these extra parts:

There maybe between 1 and 5 JobPack element structures that only contain one element: <JobPackURL1>. So the element structure would look like this:

<JobPack>
   <JobPackURL1>TestTransformation3</JobPackURL1>
</JobPack>

So the XML may look like the following (only the relevant part of the XML message, the rest is above):

<FieldSupportInformation>
            <JobPack>
                  <JobPackURL1>TestTransformation1</JobPackURL1>
            </JobPack>
            <JobPack>
                  <JobPackURL2>TestTransformation2</JobPackURL2>
            </JobPack>
            <JobPack>
                  <JobPackURL3>TestTransformation3</JobPackURL3>
            </JobPack>
            <ClosureControl>
                  <RetroStoresRequired>True</RetroStoresRequired>
                  <StoresReturnedRequired>True</StoresReturnedRequired>
                  <ReinstatementInfoRequired>True</ReinstatementInfoRequired>
                  <POIInformationRequired>True</POIInformationRequired>
                  <SurveyInformationRequired>True</SurveyInformationRequired>
                  <CalibratedEquipmentRequired>True</CalibratedEquipmentRequired>
                  <WayleaveRequired>True</WayleaveRequired>
                  <GridReferenceRequired>True</GridReferenceRequired>
                  <TestResultsRequired>True</TestResultsRequired>
            </ClosureControl>
            <AdditionalClosureDetail>
                  <Audit>
                        <Question>jhdgj&amp;kuh&gt; &lt;  &#60; of Q > uestion 1</Question>
                  </Audit>
            </AdditionalClosureDetail>
      </FieldSupportInformation>

From this we need to create the <TemporaryItemDs> element structure as before for each <JobPack>, putting the value JOBPCKx value into the <TemporaryItemCode> element, where x = to the number appended to the
<JobPackURL> element so for example for the above XML we would want the following created:


<TemporaryItemDs>
   <TemporaryItemCode>JOBPCK1</TemporaryItemCode>
   <TemporaryItemValue>Product Code</TemporaryItemValue>
</TemporaryItemDs>
<TemporaryItemDs>
   <TemporaryItemCode>JOBPCK2</TemporaryItemCode>
   <TemporaryItemValue>Product Code</TemporaryItemValue>
</TemporaryItemDs>
<TemporaryItemDs>
   <TemporaryItemCode>JOBPCK3</TemporaryItemCode>
   <TemporaryItemValue>Product Code</TemporaryItemValue>
</TemporaryItemDs>

I hope this provides enough information, and isn't too confusing. If you can help with this that would be most appreciated.

Thanks!!!
Oops, i forgot to say, i know where could perform a substring function on the <TemporaryItemCode> element value and check its value in an if statement, and then say if var = 1 then do append 1, and do the same up until 5, but we would need everything to be dynamic and not hard coded. I thought maybe assigning the value from the substring function to a variable and then checking the varibales value, and carry out the appeding accordingly, but i realise that a varibale is contant and cannot be reassigned, so i am not sure how to work around this.

Thanks again.
Actually the way i'm thinking this could be resolved is by using the substring function within the creatin of the new <TemporaryItemCode> elements as follows: however, the actual functions calls are printed out

<xsl:for-each select="../FieldSupportInformation/*[substring(local-name(), 1, 7) ='JobPack']">
              <TemporaryItemDs>
                 <TemporaryItemCode>concat(JOBPCK, ../FieldSupportInformation/*[substring(local-name(), 10, 11) ='JobPack'</TemporaryItemCode>
                    <TemporaryItemValue>"<xsl:value-of select="JobPackURL" />"</TemporaryItemValue>
                </TemporaryItemDs>
         </xsl:for-each>  

however, this is what is printed out:

<TemporaryItemDs>
   <TemporaryItemCode>concat(JOBPCK, "../FieldSupportInformation/*[substring(local-name(), 10, 11) ='JobPack'"</TemporaryItemCode>
   <TemporaryItemValue>""</TemporaryItemValue>
</TemporaryItemDs>

So firstly would my suggetsed solution be feasible? and if so, how do i amend my suggested solution so it would work?

Thank you again.
ASKER CERTIFIED SOLUTION
Avatar of anthonywjones66
anthonywjones66

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of scurtis_1

ASKER

anthonywjones66,

Thanks for all your help with this. The points are yours! :-)

Scott