Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XSLT:选择以下同级,直到到达指定的标记_Xml_Xslt - Fatal编程技术网

Xml XSLT:选择以下同级,直到到达指定的标记

Xml XSLT:选择以下同级,直到到达指定的标记,xml,xslt,Xml,Xslt,我正在尝试编写XSLT,该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>Test

我正在尝试编写XSLT,该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>

试验
测试:P1

测试:P2

测试2 测试2:p1

测试2:p2

测试2:p3

以下是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>

以下是当前的结果:

<?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>

试验
测试:P1
测试:P2
测试:p3
测试2:p1
测试2:p2
测试2
测试2:p1
测试2:p2
以下是预期结果:

<?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>

试验
测试:P1
测试:P2
测试:p3
测试2
测试2:p1
测试2:p2
试试这个:(我们不要求所有的p,而是要求所有最近上一个h1为当前的p。)


被接受的答案有不良的副作用,而且有点错误。 在这篇文章中,我将进一步解释以下基本陈述的真实比较,以及为什么可以失败


在模板中回顾/分析情况

  • 当前上下文节点是匹配的
    中的任何
    h1
  • 名为
    header
    的变量包含当前上下文节点的副本
不好/错误的基本陈述:

后面的同级::p[前面的同级::h1[1]=$header]

  • 选择我的上下文节点的所有后续同级
    p
    |
    后续同级::p
  • 过滤这些
    p
    ,其中名为
    h1
    的前一个(最近的)兄弟姐妹“与变量
    $header
    |
    相同,…[前一个兄弟姐妹::h1[1]=$header]
!!在XSLT1.0中,节点与节点的比较将通过其值来完成


请看一个例子。让我们假设输入xml如下[
包含两次相同的值
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>

试验
测试:P1

测试:P2

试验 测试2:p1

测试2:p2

测试2:p3

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>

试验
测试:P1
测试:P2

测试2:P1刚刚测试了这个,它工作得非常好。非常感谢。@Tim,虽然我们可以找到xslt的解决方案,但我还是建议您将xml格式更改为TestTest:p1

Test:p2

Test2:p1

Test2:p2

Test2:p3

,这样更有意义且可读性,在xslt中也很容易查询。为什么不编辑已接受的解决方案并添加注释呢?我对此投了反对票,因为您完全可以编辑正确的响应或留下注释。
<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>
...
<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>
...