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[las t()]">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
<xsl:for-each select="../FieldSupportInf ormation/J obPack">
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK< /Temporary ItemCode>
<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
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[las
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
<xsl:for-each select="../FieldSupportInf
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK<
<TemporaryItemValue>"<xsl:
</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
oops,
="../FieldSupportInformati on/*[subst ring(local -name(), 1, 7) = 'JobPack']">
Apostrophes missing
="../FieldSupportInformati
Apostrophes missing
JobPackURL1, JobPackURL2, etc... right? not JobPack1, JobPack2....
Pretty close to what's above then:
<xsl:for-each select="../FieldSupportInf ormation/J obPack">
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK< /Temporary ItemCode>
<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( .,'JobPack URL')]"/>
Pretty close to what's above then:
<xsl:for-each select="../FieldSupportInf
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK<
<TemporaryItemValue>"<xsl:
</TemporaryItemDs>
</xsl:for-each>
Or you could even do <xsl:value-of select="*[substring-after(
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</JobPackURL 1>
<JobPackURL2>y</JobPackURL 2>
</JobPack>
and you want something like:-
<TemporaryItemCode>JOBPCK< /Temporary ItemCode>
<TemporaryItemValue>"x"</T emporaryIt emValue>
<TemporaryItemValue>"y"</T emporaryIt emValue>
</TemporaryItemDs>
??
Then you need:-
<xsl:for-each select="../FieldSupportInf ormation/J obPack">
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK< /Temporary ItemCode>
<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="../FieldSupportInf ormation/J obPack">
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK< /Temporary ItemCode>
<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="../FieldSupportInf ormation/J obPack/*">
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK< /Temporary ItemCode>
<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="../FieldSupportInf ormation/J obPack/*[s ubstring(l ocal-name( ),1,7) = 'JobPackURL']">
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK< /Temporary ItemCode>
<TemporaryItemValue>"<xsl: value-of select="." />"</TemporaryItemValue>
</TemporaryItemDs>
</xsl:for-each>
Take you pick. :)
Anthony.
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</JobPackURL
<JobPackURL2>y</JobPackURL
</JobPack>
and you want something like:-
<TemporaryItemCode>JOBPCK<
<TemporaryItemValue>"x"</T
<TemporaryItemValue>"y"</T
</TemporaryItemDs>
??
Then you need:-
<xsl:for-each select="../FieldSupportInf
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK<
<xsl:for-each select="*[substring(local-
<TemporaryItemValue>"<xsl:
</xsl:for-each>
</TemporaryItemDs>
</xsl:for-each>
If JobPackURLn elements are the only children of JobPack then:-
<xsl:for-each select="../FieldSupportInf
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK<
<xsl:for-each select="*">
<TemporaryItemValue>"<xsl:
</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="../FieldSupportInf
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK<
<TemporaryItemValue>"<xsl:
</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="../FieldSupportInf
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK<
<TemporaryItemValue>"<xsl:
</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>TestTransform ation3</Jo bPackURL1>
</JobPack>
So the XML may look like the following (only the relevant part of the XML message, the rest is above):
<FieldSupportInformation>
<JobPack>
<JobPackURL1>TestTransform ation1</Jo bPackURL1>
</JobPack>
<JobPack>
<JobPackURL2>TestTransform ation2</Jo bPackURL2>
</JobPack>
<JobPack>
<JobPackURL3>TestTransform ation3</Jo bPackURL3>
</JobPack>
<ClosureControl>
<RetroStoresRequired>True< /RetroStor esRequired >
<StoresReturnedRequired>Tr ue</Stores ReturnedRe quired>
<ReinstatementInfoRequired >True</Rei nstatement InfoRequir ed>
<POIInformationRequired>Tr ue</POIInf ormationRe quired>
<SurveyInformationRequired >True</Sur veyInforma tionRequir ed>
<CalibratedEquipmentRequir ed>True</C alibratedE quipmentRe quired>
<WayleaveRequired>True</Wa yleaveRequ ired>
<GridReferenceRequired>Tru e</GridRef erenceRequ ired>
<TestResultsRequired>True< /TestResul tsRequired >
</ClosureControl>
<AdditionalClosureDetail>
<Audit>
<Question>jhdgj&kuh> ; < < 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 </Temporar yItemCode>
<TemporaryItemValue>Produc t Code</TemporaryItemValue>
</TemporaryItemDs>
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK2 </Temporar yItemCode>
<TemporaryItemValue>Produc t Code</TemporaryItemValue>
</TemporaryItemDs>
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK3 </Temporar yItemCode>
<TemporaryItemValue>Produc t 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!!!
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>TestTransform
</JobPack>
So the XML may look like the following (only the relevant part of the XML message, the rest is above):
<FieldSupportInformation>
<JobPack>
<JobPackURL1>TestTransform
</JobPack>
<JobPack>
<JobPackURL2>TestTransform
</JobPack>
<JobPack>
<JobPackURL3>TestTransform
</JobPack>
<ClosureControl>
<RetroStoresRequired>True<
<StoresReturnedRequired>Tr
<ReinstatementInfoRequired
<POIInformationRequired>Tr
<SurveyInformationRequired
<CalibratedEquipmentRequir
<WayleaveRequired>True</Wa
<GridReferenceRequired>Tru
<TestResultsRequired>True<
</ClosureControl>
<AdditionalClosureDetail>
<Audit>
<Question>jhdgj&kuh>
</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
<TemporaryItemValue>Produc
</TemporaryItemDs>
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK2
<TemporaryItemValue>Produc
</TemporaryItemDs>
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK3
<TemporaryItemValue>Produc
</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.
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="../FieldSupportInf ormation/* [substring (local-nam e(), 1, 7) ='JobPack']">
<TemporaryItemDs>
<TemporaryItemCode>concat( JOBPCK, ../FieldSupportInformation /*[substri ng(local-n ame(), 10, 11) ='JobPack'</TemporaryItemC ode>
<TemporaryItemValue>"<xsl: value-of select="JobPackURL" />"</TemporaryItemValue>
</TemporaryItemDs>
</xsl:for-each>
however, this is what is printed out:
<TemporaryItemDs>
<TemporaryItemCode>concat( JOBPCK, "../FieldSupportInformatio n/*[substr ing(local- name(), 10, 11) ='JobPack'"</TemporaryItem Code>
<TemporaryItemValue>""</Te mporaryIte mValue>
</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.
<xsl:for-each select="../FieldSupportInf
<TemporaryItemDs>
<TemporaryItemCode>concat(
<TemporaryItemValue>"<xsl:
</TemporaryItemDs>
</xsl:for-each>
however, this is what is printed out:
<TemporaryItemDs>
<TemporaryItemCode>concat(
<TemporaryItemValue>""</Te
</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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
anthonywjones66,
Thanks for all your help with this. The points are yours! :-)
Scott
Thanks for all your help with this. The points are yours! :-)
Scott
<xsl:for-each select="../FieldSupportInf
<TemporaryItemDs>
<TemporaryItemCode>JOBPCK<
<TemporaryItemValue>"<xsl:
</TemporaryItemDs>
</xsl:for-each>
How's this.
Anthony