Subject: [xsl] Handling Mixed Child Elements and Text() Nodes From: Brook Ellingwood <brook@xxxxxxxxxxx> Date: Tue, 30 Sep 2003 16:32:33 -0700 |
Hi, I'm running into unforeseen circumstances with the "splitting the contents of a <text> element containing <link> and <subhead> elements and text() nodes delimited by newlines into multiple <div> elements delimited by the newlines, while transforming the child elements as well" problem that I got help with from the list a while ago. The permutations I've run into now are pretty complex, so it's not surprising that the XSL is having problems. I've been trying to figure out any one of the new issues, but I'm really just taking stabs in the dark at this point. It may all be too complex to pull off with one set of templates, but I'd really like to try. Any insights would be appreciated. The biggest problem is that when I have a string of child elements separated by newlines, they aren't wrapped in the element tags, but instead are output sequentially until a sibling text() node is reached, after which the element tag is closed and a new one is begun. Less of a problem is that if the first thing encountered in the parent element is a child element it still gets contained in a <div> element with the class that a text() node in the same spot should receive as well as in one with the class that the particular child element should receive. I think I can figure this one out, but I've been focusing on the bigger issue all day and I can't see straight anymore. My third issue is that within this process, I haven't been able to find a way to translate() double newlines (" ") into singles. If I have to, I can always clean them out of the XML, but for maximum flexibility, I was hoping to handle them on the fly. Thanks in advance for any assistance. -- Brook // Sample XML: <page> <body> <text> <subhead>Linked Text</subhead> <link url="a">A</link> <link url="b">B</link> <link url="c">C</link> <link url="d">D</link> (AKA X) <link url="e">E</link> <subhead>Unlinked Text</subhead> F G H I J </text> </body> </page> // Desired Output: <div class="body_subhead">Linked Text</div> <div class="body"><a href="a" class="body">A</a></div> <div class="body"><a href="b" class="body">B</a></div> <div class="body"><a href="c" class="body">C</a></div> <div class="body"><a href="d" class="body">D</a> (AKA X)</div> <div class="body"><a href="e" class="body">E</a></div> <div class="body_subhead">Unlinked Text</div> <div class="body">F</div> <div class="body">G</div> <div class="body">H</div> <div class="body">I</div> <div class="body">J</div> // Actual output (parsed by hand for legibility): <div class="body"> <div class="body_subhead">Linked Text</div> <a href="a" class="body">A</a> <a href="b" class="body">B</a> <a href="c" class="body">D</a> (AKA X)</div> <div class="body"></div> <div class="body"><a href="e" class="body">E</a></div> </div> <div class="body_subhead">Unlinked Text</div> <div class="body">F</div> <div class="body"></div> <div class="body">G</div> <div class="body"></div> <div class="body">H</div> <div class="body"></div> <div class="body">I</div> <div class="body"></div> <div class="body">J</div> // Relevant parts of Stylesheet <xsl:key name="x" match="text/node()" use="generate-id((..|preceding-sibling::text()[contains(.,' ')][1])[last ()])"/> <xsl:key name="y" match="text/node()" use="generate-id((..|following-sibling::text()[contains(.,' ')][1])[last ()])"/> <xsl:template match="link"> <xsl:param name="linkClass"/> <xsl:param name="divClass"/> <a href="{@url}"><xsl:attribute name="class"><xsl:value-of select="$linkClass"/></xsl:attribute> <xsl:apply-templates> <xsl:with-param name="linkClass" select="$linkClass"/> </xsl:apply-templates> </a> </xsl:template> <xsl:template match="subhead"> <xsl:param name="divClass"/> <div><xsl:attribute name="class"><xsl:value-of select="$divClass"/>_subhead</xsl:attribute><xsl:value-of select="."/></div> </xsl:template> <xsl:template match="text"> <xsl:param name="divClass"/> <xsl:param name="linkClass"/> <xsl:for-each select=".|text()[contains(.,' ')]"> <xsl:call-template name="d1"> <xsl:with-param name="s" select="substring-after(self::text(),' ')"/> <xsl:with-param name="divClass" select="$divClass"/> <xsl:with-param name="linkClass" select="$linkClass"/> </xsl:call-template> </xsl:for-each> </xsl:template> <xsl:template name="d1"> <xsl:param name="s"/> <xsl:param name="divClass"/> <xsl:param name="linkClass"/> <xsl:text> </xsl:text> <xsl:choose> <xsl:when test="contains($s,' ')"> <div><xsl:attribute name="class"><xsl:value-of select="$divClass"/></xsl:attribute><xsl:value-of select="substring-before($s,' ')"/></div> <xsl:call-template name="d1"> <xsl:with-param name="s" select="substring-after($s,' ')"/> <xsl:with-param name="linkClass" select="$linkClass"/> <xsl:with-param name="divClass" select="$divClass"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <div><xsl:attribute name="class"><xsl:value-of select="$divClass"/></xsl:attribute> <xsl:value-of select="$s"/> <xsl:apply-templates select="key('x',generate-id(.))[position()<last()]"> <xsl:with-param name="linkClass" select="$linkClass"/> <xsl:with-param name="divClass" select="$divClass"/> </xsl:apply-templates> <xsl:value-of select="substring-before(key('x',generate-id(.))[last()],' ')"/> <xsl:if test="position() = last()"> <xsl:apply-templates select="key('x',generate-id(.))[last()]"> <xsl:with-param name="linkClass" select="$linkClass"/> <xsl:with-param name="divClass" select="$divClass"/> </xsl:apply-templates> </xsl:if> </div> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:for-each select="./page/body"> <xsl:apply-templates> <xsl:with-param name="textNode" select="key('x',generate-id(.))[position()<last()]"/> <xsl:with-param name="divClass" select="'body'"/> <xsl:with-param name="linkClass" select="'body'"/> </xsl:apply-templates> </xsl:for-each> // One of Many Modifications I've Tried <xsl:template match="link"> <xsl:param name="linkClass"/> <xsl:param name="divClass"/> <a href="{@url}"><xsl:attribute name="class"><xsl:value-of select="$linkClass"/></xsl:attribute> <xsl:apply-templates> <xsl:with-param name="linkClass" select="$linkClass"/> </xsl:apply-templates> </a> </xsl:template> // Output With this Modification -- Has a Bunch of New Problems <div class="body"> <div class="body_subhead">Linked Text</div> <a href="a" class="body">A</a> <div class="body"></div> <a href="b" class="body">B</a> <div class="body"></div> <a href="c" class="body">C</a> <div class="body"></div> <a href="d" class="body">D</a> <div class="body"></div> (AKA X)</div> <div class="body"></div> <div class="body"><a href="f" class="body">F</a></div> </div> <div class="body_subhead">Unlinked Text</div> <div class="body">F</div> <div class="body"></div> <div class="body">G</div> <div class="body"></div> <div class="body">H</div> <div class="body"></div> <div class="body">I</div> <div class="body"></div> <div class="body">J</div> XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Selecting First Letter, Wendell Piez | Thread | RE: [xsl] Handling Mixed Child Elem, Americo Albuquerque |
RE: [xsl] Best way to use global pa, Americo Albuquerque | Date | Re: [xsl] xpath question please, Simon Bracken |
Month |