问题
I have XML with embedded rich text formatting, which looks roughly like this:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<richtext>
<pardef/>
<par><run>This is the </run><run>preamble.</run></par>
<pardef list='bullet'/>
<par><run>This is the </run><run>first bullet.</run></par>
<par><run>This is the second </run><run>bullet.</run></par>
</richtext>
</document>
I am attempting to generate the following HTML:
<p>This is the preamble.</p>
<ul>
<li>This is the first bullet</li>
<li>This is the second bullet</li>
<ul>
I tried the following XSL but it's not working. I have a feeling that I need to use FOLLOWING-SIBLING but I'm not sure how.
<xsl:choose>
<xsl:when test="document/richtext/pardef[@list] ='bullet'">
<ul>
<xsl:for-each select="document/richtext/par/run">
<li>
<xsl:for-each select="run">
<xsl:value-of select="."/>
</xsl:for-each>
</li>
</xsl:for-each>
</ul>
</xsl:when>
<xsl:otherwise>
<p>
<xsl:for-each select="document/richtext/par">
<p>
<xsl:for-each select="run">
<xsl:value-of select="."/>
</xsl:for-each>
</p>
</xsl:for-each>
</p>
</xsl:otherwise>
</xsl:choose>
回答1:
One approach with XSLT 2.0 and your "design":
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:key name="key-for-par" match="document/richtext/par" use="generate-id(preceding-sibling::pardef[1])"/>
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="document/richtext/pardef" />
</xsl:template>
<xsl:template match="pardef[@list = 'bullet']">
<ul>
<xsl:for-each select="key('key-for-par', generate-id(.))">
<li>
<xsl:value-of select="run" separator=""/>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="pardef[not(@list)]">
<p>
<xsl:for-each select="key('key-for-par', generate-id(.))">
<p>
<xsl:value-of select="run" separator=""/>
</p>
</xsl:for-each>
</p>
</xsl:template>
</xsl:stylesheet>
EDIT 1: improved version.
来源:https://stackoverflow.com/questions/40027337/how-to-use-xslkey-to-get-the-following-sibling-in-xslt-2-0