?
Solved

XSLT: Repeating tag needs to be transformed?

Posted on 2005-04-08
9
Medium Priority
?
198 Views
Last Modified: 2012-06-27
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
0
Comment
Question by:scurtis_1
9 Comments
 
LVL 8

Expert Comment

by:anthonywjones66
ID: 13738214
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
0
 
LVL 8

Expert Comment

by:anthonywjones66
ID: 13738224
oops,

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

Apostrophes missing
0
 
LVL 12

Expert Comment

by:jkmyoung
ID: 13741201
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')]"/>
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 8

Expert Comment

by:anthonywjones66
ID: 13744238
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.



0
 

Expert Comment

by:cbridle
ID: 13751455
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!!!
0
 

Expert Comment

by:cbridle
ID: 13751512
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.
0
 

Expert Comment

by:cbridle
ID: 13751547
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.
0
 
LVL 8

Accepted Solution

by:
anthonywjones66 earned 2000 total points
ID: 13751938
Since the JobPack elements only ever containt JobPackURLn elements then the for-each select:-

../FieldSupportInformation/JobPack/*

should be ok.

Thus the solution looks like:-

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

Anthony.
0
 

Author Comment

by:scurtis_1
ID: 13752164
anthonywjones66,

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

Scott
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
Create a Windows 10 custom Image with custom task bar and custom start menu using XML for deployment.
this video summaries big data hadoop online training demo (http://onlineitguru.com/big-data-hadoop-online-training-placement.html) , and covers basics in big data hadoop .
Screencast - Getting to Know the Pipeline
Suggested Courses

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question