我正在尝试编写XSLT,它将在选定的后续兄弟节点上运行for-each,但在到达另一个标签(h1)时停止.
这是源XML:
<?xml version="1.0"?>
<html>
<h1>Test</h1>
<p>Test: p 1</p>
<p>Test: p 2</p>
<h1>Test 2</h1>
<p>Test2: p 1</p>
<p>Test2: p 2</p>
<p>Test2: p 3</p>
</html>
Run Code Online (Sandbox Code Playgroud)
这是XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<content>
<xsl:apply-templates/>
</content>
</xsl:template>
<xsl:template match="h1">
<section>
<sectionHeading>
<xsl:apply-templates/>
</sectionHeading>
<sectionContent>
<xsl:for-each select="following-sibling::p">
<paragraph>
<xsl:value-of select="."/>
</paragraph>
</xsl:for-each>
</sectionContent>
</section>
</xsl:template>
<xsl:template match="p"/>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
这是当前的结果:
<?xml version="1.0" encoding="UTF-8"?>
<content>
<section>
<sectionHeading>Test</sectionHeading>
<sectionContent>
<paragraph>Test: p 1</paragraph>
<paragraph>Test: p 2</paragraph>
<paragraph>Test: p 3</paragraph>
<paragraph>Test2: p 1</paragraph>
<paragraph>Test2: p 2</paragraph>
</sectionContent>
</section>
<section>
<sectionHeading>Test 2</sectionHeading>
<sectionContent>
<paragraph>Test2: p 1</paragraph>
<paragraph>Test2: p 2</paragraph>
</sectionContent>
</section>
</content>
Run Code Online (Sandbox Code Playgroud)
这是预期的结果:
<?xml version="1.0" encoding="UTF-8"?>
<content>
<section>
<sectionHeading>Test</sectionHeading>
<sectionContent>
<paragraph>Test: p 1</paragraph>
<paragraph>Test: p 2</paragraph>
<paragraph>Test: p 3</paragraph>
</sectionContent>
</section>
<section>
<sectionHeading>Test 2</sectionHeading>
<sectionContent>
<paragraph>Test2: p 1</paragraph>
<paragraph>Test2: p 2</paragraph>
</sectionContent>
</section>
</content>
Run Code Online (Sandbox Code Playgroud)
Kyl*_*utt 25
试试这个:(而不是要求所有的p,我们要求所有的p,其最近的前一个h1是当前的.)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<content>
<xsl:apply-templates/>
</content>
</xsl:template>
<xsl:template match="h1">
<xsl:variable name="header" select="."/>
<section>
<sectionHeading>
<xsl:apply-templates/>
</sectionHeading>
<sectionContent>
<xsl:for-each select="following-sibling::p[preceding-sibling::h1[1] = $header]">
<paragraph>
<xsl:value-of select="."/>
</paragraph>
</xsl:for-each>
</sectionContent>
</section>
</xsl:template>
<xsl:template match="p"/>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
此外,在这篇文章中,我将解释真正比较下列基本语句,以及为什么它可以和会失败.
在模板中回顾/分析情况<xsl:template match="h1">:
h1匹配中的任何一个<xsl:template>.header包含我当前上下文节点的副本.坏/坏的基本陈述:
follow-sibling :: p [preceding-sibling :: h1 [1] = $ header]
p我的上下文节点的所有以下兄弟节点following-sibling::pp名为h1 "is"的第一个(最近的)前同胞与变量$header| 相同的位置 ...[preceding-sibling::h1[1] = $header].!在XSLT 1.0中,节点与节点的比较将通过其值来完成!
在一个例子中看到它.让我们假装输入xml是这样的[ <h1>包含两倍相同的值Test]:
<html>
<h1>Test</h1>
<p>Test: p 1</p>
<p>Test: p 2</p>
<h1>Test</h1>
<p>Test2: p 1</p>
<p>Test2: p 2</p>
<p>Test2: p 3</p>
</html>
Run Code Online (Sandbox Code Playgroud)
A !错!结果将被创建:
<content>
<section>
<sectionHeading>Test</sectionHeading>
<sectionContent>
<paragraph>Test: p 1</paragraph>
<paragraph>Test: p 2</paragraph>
<paragraph>Test2: p 1</paragraph> <-- should be only in 2. section
<paragraph>Test2: p 2</paragraph> <-- should be only in 2. section
<paragraph>Test2: p 3</paragraph> <-- should be only in 2. section
</sectionContent>
</section>
<section>
<sectionHeading>Test</sectionHeading>
<sectionContent>
<paragraph>Test2: p 1</paragraph>
<paragraph>Test2: p 2</paragraph>
<paragraph>Test2: p 3</paragraph>
</sectionContent>
</section>
</content>
Run Code Online (Sandbox Code Playgroud)
...
<xsl:template match="h1">
<xsl:variable name="header" select="generate-id(.)"/>
<section>
<sectionHeading>
<xsl:apply-templates/>
</sectionHeading>
<sectionContent>
<xsl:for-each select="following-sibling::p[generate-id(preceding-sibling::h1[1]) = $header]">
<paragraph>
<xsl:value-of select="."/>
</paragraph>
</xsl:for-each>
</sectionContent>
</section>
</xsl:template>
...
Run Code Online (Sandbox Code Playgroud)
使用函数generate-id()获取节点的唯一ID(至少在当前文档中),并比较现在节点与节点!即使你使用这种技术<xsl:key>,你也必须使用generate-id!