Jump to content

Conditionally Looping Through Preceding Siblings


fistofzen

Recommended Posts

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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>

Link to comment
Share on other sites

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>

Link to comment
Share on other sites

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>

Link to comment
Share on other sites

Archived

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

×
×
  • Create New...