我试图使用一个键对<p>元素进行分组,这是基于它们是否有特定的处理指令作为第一个兄弟姐妹,但是我没有运气。
对于下面的示例输入,我希望每个具有包含“key”的第一个同级处理指令的<p>与符合相同条件的同级<p>元素进行分组。示例输入:
<root>
<p>not in key</p>
<?samplePI key?>
<p>start of key; </p>
<?samplePI key?>
<p>in key 1; </p>
<?samplePI key?>
<p>in key 2; </p>
<p>Not in key</p>
<?samplePI key?>
<p>start of new key; </p>
<?samplePI key?>
<p>in new key 3;</p>
</root>示例输出:
<root>
<p>not in key</p>
<p>start of key; in key 1; in key 2;</p>
<p>Not in key</p>
<p>start of new key; in new key 3;</p>
</root>我得到的一个例子是:
<xsl:template match="root">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="p">
<xsl:choose>
<xsl:when test="preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]][preceding-sibling::p[1][(preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]])]]">
</xsl:when>
<xsl:when test="preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]][preceding-sibling::p[1][not(preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]])]]">
<p><xsl:value-of select="text()"/>
<xsl:apply-templates select="key('nodes', generate-id())" mode="groupedParas"/>
</p>
</xsl:when>
<xsl:otherwise>
<p><xsl:apply-templates/></p>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="p" mode="groupedParas">
<xsl:apply-templates/>
</xsl:template>
<xsl:key name="nodes" match="node()[(self::p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]])]" use="generate-id((preceding-sibling::p)[last()])"/>
<xsl:template match="text()">
<xsl:value-of select="."/>
</xsl:template> 注意,我需要帮助获得正确的键语法,而不是生成所需的结构。为此,我需要使用XSLT1.0。任何帮助都很感激。
发布于 2014-05-06 16:29:40
使用XSLT2.0看起来是可管理的
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="root">
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="boolean(preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<p>
<xsl:apply-templates select="current-group()/node()"/>
</p>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>使用XSLT1.0,我通常的方法是同级递归,但它需要冗长而复杂的匹配模式:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="processing-instruction()[contains(., 'key')]"/>
<xsl:template match="p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]
and preceding-sibling::node()[2][not(self::p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]])]]">
<p>
<xsl:apply-templates select="." mode="collect"/>
</p>
</xsl:template>
<xsl:template match="p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]
and preceding-sibling::node()[2][self::p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]]]]"/>
<xsl:template match="p" mode="collect">
<xsl:apply-templates/>
<xsl:apply-templates select="following-sibling::node()[2][self::p and preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]]" mode="collect"/>
</xsl:template>
</xsl:stylesheet>最后,正如您似乎希望使用一个键一样,上面显示的使用key标识一组p元素的同级递归的一个变体如下:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:key name="collect"
match="p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]
and preceding-sibling::node()[2][self::p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]]]]"
use="generate-id(preceding-sibling::p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]
and not(preceding-sibling::node()[2][self::p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]]])][1])"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="processing-instruction()[contains(., 'key')]"/>
<xsl:template match="p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]
and preceding-sibling::node()[2][not(self::p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]])]]">
<p>
<xsl:apply-templates select="./node() | key('collect', generate-id())/node()"/>
</p>
</xsl:template>
<xsl:template match="p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]
and preceding-sibling::node()[2][self::p[preceding-sibling::node()[1][self::processing-instruction()[contains(., 'key')]]]]]"/>
</xsl:stylesheet>https://stackoverflow.com/questions/23497667
复制相似问题