Subject: [xsl] Fwd: [BigList Fwd] Re: XML: From flat to hierarchical with grouping From: "nick public nickpubl@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Wed, 29 Mar 2017 23:51:44 -0000 |
Hi Patrik, Thank you very much for your help. I appreciate your solution of rec2 recursion key. It's a good idea! For XSLT 2.0, unfortunatelly it's unsupported. Perhaps is for this that <xsl:copy> <xsl:for-each-group select="*" group-starting-with="rec1"> fails with the error : "xsl:for-each-group cannot be child of xsl:copy" Could you help me, please, with a solution in XSLT 1.0? Thanks a lot Nicola ---------- Messaggio inoltrato ---------- From: nick public <nickpubl@xxxxxxxxx> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx Cc: Bcc: Date: Wed, 29 Mar 2017 04:11:57 +0200 Subject: XML: From flat to hierarchical with grouping I need to manipolate this XML: <root> <row> <rec1> <fld1-1/> </rec1> <rec2> <fld2-1/> </rec2> <rec3> <fld3-1/> </rec3> <rec3> <fld3-2/> </rec3> <rec2> <fld2-2/> </rec2> <rec3> <fld3-3/> </rec3> <rec3> <fld3-4/> </rec3> </row> <row> <rec1> <fld1-2/> </rec1> <rec2> <fld2-3/> </rec2> <rec3> <fld3-5/> </rec3> <rec3> <fld3-6/> </rec3> <rec2> <fld2-4/> </rec2> <rec3> <fld3-7/> </rec3> <rec3> <fld3-8/> </rec3> </row> </root> to convert it in this other hierarchical structure <root_new> <row> <rec1> <fld1-1/> <rec2> <fld2-1/> <rec3> <fld3-1/> </rec3> <rec3> <fld3-2/> </rec3> </rec2> <rec2> <fld2-2/> <rec3> <fld3-3/> </rec3> <rec3> <fld3-4/> </rec3> </rec2> </rec1> </row> <row> <rec1> <fld1-2/> <rec2> <fld2-3/> <rec3> <fld3-5/> </rec3> <rec3> <fld3-6/> </rec3> </rec2> <rec2> <fld2-4/> <rec3> <fld3-7/> </rec3> <rec3> <fld3-8/> </rec3> </rec2> </rec1> </row> </root_new> To better explain, for each <row> element I have to include in <rec1>, just 1 per <row>, all <rec2> in same <row> and in each <rec2> all following <rec3> until next <rec2> in same <row>. row-rec1-rec2-rec3-rec3-rec2-rec3 have to e transformed in row rec1 rec2 rec3 rec3 rec2 rec3 <rec1>, <rec2> and <rec3> have own fields <fld*>. With following script <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" <xsl:output method="xml" indent="yes"/> <xsl:key name="k2" match="rec2" use="generate-id(preceding-sibling::rec1[1])" /> <xsl:key name="k3" match="rec3" use="generate-id(preceding-sibling::rec2[1])" /> <xsl:template match="/"> <root_new> <xsl:apply-templates select="//root/row" /> </root_new> </xsl:template> <xsl:template match="//row"> <xsl:copy> <xsl:apply-templates select="rec1" /> </xsl:copy> </xsl:template> <xsl:template match="rec1"> <xsl:copy> <xsl:copy-of select="./*"/> <xsl:copy-of select="key('k2', generate-id())"/> <xsl:apply-templates select="rec2" /> </xsl:copy> </xsl:template> <xsl:template match="rec2"> <xsl:copy> <xsl:copy-of select="./*"/> <xsl:copy-of select="key('k3', generate-id())"/> </xsl:copy> </xsl:template> </xsl:stylesheet> I can obtain this partial result <?xml version="1.0" encoding="utf-8"?> <root_new> <row> <rec1> <fld1-1 /> <rec2> <fld2-1 /> </rec2> <rec2> <fld2-2 /> </rec2> </rec1> </row> <row> <rec1> <fld1-2 /> <rec2> <fld2-3 /> </rec2> <rec2> <fld2-4 /> </rec2> </rec1> </row> </root_new> but I'm not able to include the <rec3> elements under the <rec2> that precede them. Could you help me please? Ciao from Italy Nicola -------------------------------------------------------- Do you need to index your XML? Try the OpenSource XMLSmartHelper Framework ---------- Messaggio inoltrato ---------- From: "Dr. Patrik Stellmann" <Patrik.Stellmann@xxxxxxxxx> To: "xsl-list@xxxxxxxxxxxxxxxxxxxxxx" <xsl-list@xxxxxxxxxxxxxxxxxxxxxx> Cc: Bcc: Date: Wed, 29 Mar 2017 04:41:31 +0000 Subject: AW: [xsl] XML: From flat to hierarchical with grouping Hi Nicola, you need to process the rec2 elements that you got with key('k2', generate-id()) recursively instead of just copying them. And since rec1 does not contain rec2 elements the <xsl:apply-templates select="rec2" /> has no effect. So this template should work: <xsl:template match="rec1"> <xsl:copy> <xsl:copy-of select="./*"/> <xsl:apply-templates select="key('k2', generate-id())"/> </xsl:copy> </xsl:template> And if XSLT 2.0 is an option you could write it like this: <xsl:template match="row"> <xsl:copy> <xsl:for-each-group select="*" group-starting-with="rec1"> <xsl:copy> <xsl:copy-of select="*"/> <xsl:for-each-group select="current-group()[position() > 1]" group-starting-with="rec2"> <xsl:copy> <xsl:copy-of select="*"/> <xsl:copy-of select="current-group()[position() > 1]"/> </xsl:copy> </xsl:for-each-group> </xsl:copy> </xsl:for-each-group> </xsl:copy> </xsl:template> Some comments to the other code: - <xsl:apply-templates select="//root/row" /> will look for any root element on any level. If you know the root element can only be on top level you should use select="root/row". - <xsl:template match="//row"> is identical to <xsl:template match="row"> - <xsl:copy-of select="./*"/> is identical to <xsl:copy-of select="*"/> Regards, Patrik ------------------------------------------------------------------ Systemarchitektur & IT-Projekte Tel: +49 40 33449-1142 Fax: +49 40 33449-1400 E-Mail: mailto:Patrik.Stellmann@xxxxxxxxx
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] XML: From flat to hierarc, Michael Kay mike@xxx | Thread | Re: [xsl] [BigList Fwd] Re: XML: Fr, Michael Kay mike@xxx |
Re: [xsl] XML: From flat to hierarc, Michael Kay mike@xxx | Date | Re: [xsl] [BigList Fwd] Re: XML: Fr, Michael Kay mike@xxx |
Month |