Jump to content

Conditionally Looping Through Preceding Siblings


fistofzen

Recommended Posts

Posted

I have this xml <root><p> <span> <tag>Foo</tag> <br/> </span></p><p> <span> <tag>Foo</tag> <br/> </span> <span> <tag>Foo</tag> </span> <span> <tag>Foo</tag> <br/> </span></p><p> <span> <tag>Foo</tag> </span> <span> <tag>Foo</tag> <br/> </span> <span> <tag>Foo</tag> </span> <span> <tag>Foo</tag> </span> <span> <tag>Foo</tag> <br/> </span></p></root> and I'm trying to get the following with xslt1.0 <root><p> <span> <tag>Foo</tag> </span></p><p> <span> <tag>Foo</tag> </span></p><p> <span> <tag>Foo</tag> </span> <span> <tag>Foo</tag> </span></p><p> <span> <tag>Foo</tag> </span> <span> <tag>Foo</tag> </span></p><p> <span> <tag>Foo</tag> </span> <span> <tag>Foo</tag> </span> <span> <tag>Foo</tag> </span></p></root> Here is the XSLT <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:key name="para" match="Content" use="generate-id(following-sibling::br[1])" /> <xsl:template match="p"> <xsl:apply-templates select="br" /> <xsl:if test="Content[not(following-sibling::br)]"> <p> <xsl:apply-templates select="Content[not(following-sibling::br)]" /> </p> </xsl:if> </xsl:template> <xsl:template match="br"> <p> <xsl:apply-templates select="key('para', generate-id())" /> </p> </xsl:template> <xsl:template match="span"> <span> <xsl:apply-templates select="Content" /> </span> </xsl:template> <xsl:template match="Content"> <Content> <xsl:value-of select="."/> </Content> </xsl:template></xsl:stylesheet> Which is clearly wrong for this XML but is the nearest I can get. Any help is would be greatly appreciated.

Posted

I am struggling to understand the criteria defining in which way the XML should be transformed. As all "tag" elements in the sample have the same contents "Foo" it is difficult to identify which elements in the input sample end up at which position in the result sample. And the stylesheet you have posted has stuff like match="Content" although I don't see any elements of that name in the input sample. So posting an input and desired result sample is a good way to allow us to understand what kind of transformation you want to achieve but it would help if you write some sentences as well to explain what kind of transformation you want.

Posted

Apologies for sloppyness - I want to transform all the <br/> tags into <p> tags there are three <p> tags in the original XML and I want to end up with 5. Here is the re-freshed XSL <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:key name="para" match="tag" use="generate-id(following-sibling::br[1])" /> <xsl:template match="p"> <xsl:apply-templates select="br" /> <xsl:if test="tag[not(following-sibling::br)]"> <p> <xsl:apply-templates select="tag[not(following-sibling::br)]" /> </p> </xsl:if> </xsl:template> <xsl:template match="br"> <p> <xsl:apply-templates select="key('para', generate-id())" /> </p> </xsl:template> <xsl:template match="span"> <span> <xsl:apply-templates select="Content" /> </span> </xsl:template> <xsl:template match="Content"> <Content> <xsl:value-of select="."/> </Content> </xsl:template></xsl:stylesheet> many thanks for your help

Posted

correction <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="xml" indent="yes"/><xsl:key name="para" match="tag" use="generate-id(following-sibling::br[1])" /><xsl:template match="p"><xsl:apply-templates select="br" /><xsl:if test="tag[not(following-sibling::br)]"><p><xsl:apply-templates select="tag[not(following-sibling::br)]" /></p></xsl:if></xsl:template><xsl:template match="br"><p><xsl:apply-templates select="key('para', generate-id())" /></p></xsl:template><xsl:template match="span"><span><xsl:apply-templates select="tag" /></span></xsl:template><xsl:template match="tag"><tag><xsl:value-of select="."/></tag></xsl:template></xsl:stylesheet>

Posted

Here is an XSLT 1.0 sample using sibling recursion:

<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0">   <xsl:output method="xml" indent="yes"/>  <xsl:strip-space elements="*"/>   <xsl:template match="@* | node()">    <xsl:copy>	  <xsl:apply-templates select="@* | node()"/>    </xsl:copy>  </xsl:template>   <xsl:template match="p">    <xsl:apply-templates select="span[1]" mode="group"/>  </xsl:template>   <xsl:template match="span[not(br)]" mode="group">    <p>	  <xsl:apply-templates select="."/>    </p>    <xsl:apply-templates select="following-sibling::span[br][1]/following-sibling::span[1]" mode="group"/>  </xsl:template>   <xsl:template match="span[br]" mode="group">    <p>	  <xsl:apply-templates select="."/>    </p>    <xsl:apply-templates select="following-sibling::span[1]" mode="group"/>  </xsl:template>    <xsl:template match="span[not(br)]">    <xsl:copy>	  <xsl:apply-templates select="@* | node()"/>    </xsl:copy>    <xsl:apply-templates select="following-sibling::span[1]"/>  </xsl:template>   <xsl:template match="span/br"/></xsl:stylesheet>   

Saxon 6.5.5, when applied to the input sample

<root>  <p>    <span>	  <tag>Foo 1</tag>	  <br/>    </span>  </p>  <p>    <span>	  <tag>Foo 2</tag>	  <br/>    </span>    <span>	  <tag>Foo 3</tag>    </span>    <span>	  <tag>Foo 4</tag>	  <br/>    </span>  </p>  <p>    <span>	  <tag>Foo 5</tag>    </span>    <span>	  <tag>Foo 6</tag>	  <br/>    </span>    <span>	  <tag>Foo 7</tag>    </span>    <span>	  <tag>Foo 8</tag>    </span>    <span>	  <tag>Foo 9</tag>	  <br/>    </span>  </p></root>

outputs

<root>   <p>	  <span>		 <tag>Foo 1</tag>	  </span>   </p>   <p>	  <span>		 <tag>Foo 2</tag>	  </span>   </p>   <p>	  <span>		 <tag>Foo 3</tag>	  </span>	  <span>		 <tag>Foo 4</tag>	  </span>   </p>   <p>	  <span>		 <tag>Foo 5</tag>	  </span>	  <span>		 <tag>Foo 6</tag>	  </span>   </p>   <p>	  <span>		 <tag>Foo 7</tag>	  </span>	  <span>		 <tag>Foo 8</tag>	  </span>	  <span>		 <tag>Foo 9</tag>	  </span>   </p></root>

Posted

Fantastic - very helpful - if I can add one small addition to the XML input. The change is at the bottom (Foo 9). I would also like to inject <p> tags in the smae way here.Many thanks for your help and time. Amazing! <root> <p> <span> <tag>Foo 1</tag> <br/> </span> </p> <p> <span> <tag>Foo 2</tag> <br/> </span> <span> <tag>Foo 3</tag> </span> <span> <tag>Foo 4</tag> <br/> </span> </p> <p> <span> <tag>Foo 5</tag> </span> <span> <tag>Foo 6</tag> <br/> </span> <span> <tag>Foo 7</tag> </span> <span> <tag>Foo 8</tag> </span> <span> <tag>Foo 9</tag> <br/> <tag>Foo 9</tag> <br/> <tag>Foo 9</tag> <br/> <tag>Foo 9</tag> </span> </p></root>

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...