3

这是我的 XML 文档(小片段)。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

<w:body>

    <w:p> <!-- Current Node -->
        <w:pPr>
            <w:pStyle w:val="Heading1"/>
        </w:pPr>

        <w:r>
            <w:t>
                 Paragraph1
            </w:t>
        </w:r>
    </w:p>

    <w:tbl>
        <w:t>table info
        </w:t>
    </w:tbl>

    <w:p>
        <w:pPr>
        </w:pPr>
        <w:r>
            <w:t>
                 Paragraph2
            </w:t>
        </w:r>
    </w:p>

    <w:p>
        <w:pPr>
        </w:pPr>
        <w:r>
            <w:t>
                 Paragraph3
            </w:t>
        </w:r>
    </w:p>

    <w:p>
        <w:pPr>
            <w:pStyle w:val="Heading1"/>
        </w:pPr>

        <w:r>
            <w:t>
                 Paragraph4
            </w:t>
        </w:r>
    </w:p>

    <w:p>
        <w:pPr>
        </w:pPr>
        <w:r>
            <w:t>
                 Paragraph5
            </w:t>
        </w:r>
    </w:p>

    <w:p>
        <w:pPr>
            <w:pStyle w:val="Heading1"/>
        </w:pPr>

        <w:r>
            <w:t>
                 Paragraph6
            </w:t>
        </w:r>
    </w:p>

</w:body>
</w:document>

在这里,我想选择第一个<w:p>using for-each 语句的下一个兄弟,直到它遇到下一个<w:p>具有其<w:pPr><w:pStyle w:val="Heading1"/></w:pPr>.

例如,首先<w:p>我想只选择接下来的三个兄弟姐妹。(即,第 2 段、第 3 段并包括表格信息)。因为,第 4 个<w:p><w:pPr><w:pStyle w:val="Heading1"/></w:pPr>.

<w:p>如果是当前节点,则第 4 个情况相同。然后我只想选择 5th <w:p>

我不知道如何在 for-each 中指定这个条件。所以,你能指导我得到这个......

我需要的输出是这样的:

<Document>
   <Heading1>
        <paragraph>paragrap1</paragraph>
        <paragraph>table info</paragraph>
        <paragraph>paragrap2</paragraph>
        <paragraph>paragrap3</paragraph>
   </Heading1>
   <Heading1>
        <paragraph>paragrap4</paragraph>
        <paragraph>paragrap5</paragraph>
   </Heading1>
   <Heading1>
        <paragraph>paragrap6</paragraph>
   </Heading1>
</Document>
4

4 回答 4

2

在这里,我想选择第一个<w:p> usingfor-each语句的下一个兄弟,直到它遇到下一个<w:p>具有<w:pPr><w:pStyle w:val="Heading1"/></w:pPr>.

此 XSLT 2.0 转换显示了使用 XPAth 2.0 运算符的一种方法 >>

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
  exclude-result-prefixes="w xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="*/w:p[1]">

  <xsl:variable name="vNextWP" select=
  "following-sibling::w:p
    [w:pPr/w:pStyle/@w:val='Heading1']
     [1]
  "/>

  <xsl:copy-of select=
  "following-sibling::w:p[$vNextWP >> .]"/>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>

应用于提供的 XML 文档时

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

    <w:body>

        <w:p> <!-- Current Node -->
            <w:pPr>
                <w:pStyle w:val="Heading1"/>
            </w:pPr>

            <w:r>
                <w:t>
                     Paragraph1
                </w:t>
            </w:r>
        </w:p>

        <w:p>
            <w:pPr>
            </w:pPr>
            <w:r>
                <w:t>
                     Paragraph2
                </w:t>
            </w:r>
        </w:p>

        <w:p>
            <w:pPr>
            </w:pPr>
            <w:r>
                <w:t>
                     Paragraph3
                </w:t>
            </w:r>
        </w:p>

        <w:p>
            <w:pPr>
                <w:pStyle w:val="Heading1"/>
            </w:pPr>

            <w:r>
                <w:t>
                     Paragraph4
                </w:t>
            </w:r>
        </w:p>

        <w:p>
            <w:pPr>
            </w:pPr>
            <w:r>
                <w:t>
                     Paragraph5
                </w:t>
            </w:r>
        </w:p>

        <w:p>
            <w:pPr>
                <w:pStyle w:val="Heading1"/>
            </w:pPr>

            <w:r>
                <w:t>
                     Paragraph6
                </w:t>
            </w:r>
        </w:p>

    </w:body>
</w:document>

正是想要的节点被选中并复制到输出

<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
            <w:pPr>
            </w:pPr>
            <w:r>
                <w:t>
                     Paragraph2
                </w:t>
            </w:r>
        </w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
            <w:pPr>
            </w:pPr>
            <w:r>
                <w:t>
                     Paragraph3
                </w:t>
            </w:r>
        </w:p>

更新:OP已经澄清了转换的结果是什么(分组),所以这里是:

一、XSLT 1.0 解决方案

 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
 exclude-result-prefixes="w">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kFollowing"
  match="w:p[not(w:pPr/w:pStyle/@w:val = 'Heading1')]
        |
         w:tbl"
  use="generate-id(preceding-sibling::w:p
           [w:pPr/w:pStyle/@w:val = 'Heading1'][1])
  "/>

 <xsl:template match="/*">
  <Document>
   <xsl:apply-templates/>
  </Document>
 </xsl:template>

 <xsl:template match=
 "w:p[w:pPr/w:pStyle/@w:val = 'Heading1']">

  <Heading1>
   <xsl:apply-templates mode="inGroup" select=
    ". | key('kFollowing', generate-id())"/>
   </Heading1>
 </xsl:template>

 <xsl:template match="*" mode="inGroup">
  <paragraph>
    <xsl:value-of select="normalize-space(.//w:t)"/>
  </paragraph>
 </xsl:template>

 <xsl:template match="w:body/*" priority="-1"/>
</xsl:stylesheet>

当此转换应用于新提供的 XML 文档时

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

<w:body>

    <w:p> <!-- Current Node -->
        <w:pPr>
            <w:pStyle w:val="Heading1"/>
        </w:pPr>

        <w:r>
            <w:t>
                 Paragraph1
            </w:t>
        </w:r>
    </w:p>

    <w:tbl>
        <w:t>table info
        </w:t>
    </w:tbl>

    <w:p>
        <w:pPr>
        </w:pPr>
        <w:r>
            <w:t>
                 Paragraph2
            </w:t>
        </w:r>
    </w:p>

    <w:p>
        <w:pPr>
        </w:pPr>
        <w:r>
            <w:t>
                 Paragraph3
            </w:t>
        </w:r>
    </w:p>

    <w:p>
        <w:pPr>
            <w:pStyle w:val="Heading1"/>
        </w:pPr>

        <w:r>
            <w:t>
                 Paragraph4
            </w:t>
        </w:r>
    </w:p>

    <w:p>
        <w:pPr>
        </w:pPr>
        <w:r>
            <w:t>
                 Paragraph5
            </w:t>
        </w:r>
    </w:p>

    <w:p>
        <w:pPr>
            <w:pStyle w:val="Heading1"/>
        </w:pPr>

        <w:r>
            <w:t>
                 Paragraph6
            </w:t>
        </w:r>
    </w:p>

</w:body>
</w:document>

产生了想要的正确结果

<Document>
   <Heading1>
      <paragraph>Paragraph1</paragraph>
      <paragraph>table info</paragraph>
      <paragraph>Paragraph2</paragraph>
      <paragraph>Paragraph3</paragraph>
   </Heading1>
   <Heading1>
      <paragraph>Paragraph4</paragraph>
      <paragraph>Paragraph5</paragraph>
   </Heading1>
   <Heading1>
      <paragraph>Paragraph6</paragraph>
   </Heading1>
</Document>

二、XSLT 2.0 解决方案

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
  exclude-result-prefixes="w"   >
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
     <Document>
      <xsl:for-each-group
      select="*/*"
      group-starting-with="w:p[w:pPr/w:pStyle/@w:val = 'Heading1']">
       <Heading1>
         <xsl:for-each select="current-group()//w:t">
           <paragraph>
             <xsl:sequence select="normalize-space(.)"/>
           </paragraph>
         </xsl:for-each>
       </Heading1>
      </xsl:for-each-group>
     </Document>
 </xsl:template>
</xsl:stylesheet>

当这个 XSLT 2.0 转换应用于同一个 XML 文档(上图)时,会产生同样想要的正确结果

<Document>
   <Heading1>
      <paragraph>Paragraph1</paragraph>
      <paragraph>table info</paragraph>
      <paragraph>Paragraph2</paragraph>
      <paragraph>Paragraph3</paragraph>
   </Heading1>
   <Heading1>
      <paragraph>Paragraph4</paragraph>
      <paragraph>Paragraph5</paragraph>
   </Heading1>
   <Heading1>
      <paragraph>Paragraph6</paragraph>
   </Heading1>
</Document>
于 2011-12-28T06:48:27.917 回答
2

这可以通过将x:t元素按第一个前面的w:pPr/w:pStyle元素分组的键来实现(在 XSLT 1.0 中)

<xsl:key 
   name="text" 
   match="w:t" 
   use="generate-id(preceding::w:pPr[w:pStyle][1]/w:pStyle)" />

然后,对于任何(或所有)特定的w:pStyle元素,您可以获取所有关联的文本元素,如下所示

<xsl:apply-templates select="key('text', generate-id())" />

所以,下面的 XSLT....

<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
  exclude-result-prefixes="w">

   <xsl:output method="xml" indent="yes" />

   <xsl:key 
      name="text" 
      match="w:t" 
      use="generate-id(preceding::w:pPr[w:pStyle][1]/w:pStyle)" />

   <xsl:template match="/">
      <Document>
         <xsl:apply-templates select="//w:pPr/w:pStyle" />
      </Document>
   </xsl:template>

   <xsl:template match="w:pStyle">
      <xsl:element name="{@w:val}">
         <xsl:apply-templates select="key('text', generate-id())" />
      </xsl:element>
   </xsl:template>

   <xsl:template match="w:t">
      <paragraph><xsl:value-of select="normalize-space(.)" /></paragraph>
   </xsl:template>
</xsl:stylesheet>

当应用于您的示例输入 XML 文档时,将输出以下内容:

<Document>
   <Heading1>
      <paragraph>Paragraph1</paragraph>
      <paragraph>table info</paragraph>
      <paragraph>Paragraph2</paragraph>
      <paragraph>Paragraph3</paragraph>
   </Heading1>
   <Heading1>
      <paragraph>Paragraph4</paragraph>
      <paragraph>Paragraph5</paragraph>
   </Heading1>
   <Heading1>
      <paragraph>Paragraph6</paragraph>
   </Heading1>
</Document>
于 2011-12-28T15:36:38.247 回答
0

还有另一种方法,使用 CDATA 稍微作弊,这是我的版本

1/ 对于第一个和最后一个 position() 元素,我使用 CDATA 打开和关闭<Heading1>标签,

2/如果你在第一个和最后一个之间并且w:p元素有一个Heading1,我相信一个 Heading1 标签必须关闭而另一个打开。

3/ 如果没有匹配项,你必须是一个段落。

  <xsl:for-each select="//w:body/*">
        <xsl:choose>
            <!-- If you are the first one, create the heading element -->
            <xsl:when test="position() = 1">
                <xsl:text disable-output-escaping="yes">
                <![CDATA[
                <Heading1>
                ]]>
                </xsl:text>
                <paragraph>
                    <xsl:value-of select=".//w:t" />
                </paragraph>
            </xsl:when>
            <!-- If you are last close the element -->
            <xsl:when test="position() = last()">
                <paragraph>
                    <xsl:value-of select=".//w:t" />
                </paragraph>
                <xsl:text disable-output-escaping="yes">
                <![CDATA[
                </Heading1>
                ]]>
                </xsl:text>
            </xsl:when>
            <!-- If you are in-between first and last open and close -->
            <xsl:when test="w:pPr/w:pStyle/@w:val = 'Heading1'">
                <xsl:text disable-output-escaping="yes">
                <![CDATA[
                </Heading1><Heading1>
                ]]>
                </xsl:text>
                <!-- Nothing matches that means we need to pick up the paragraph -->
                <paragraph>
                    <xsl:value-of select=".//w:t" />
                </paragraph>
            </xsl:when>
            <xsl:otherwise>
                <!-- Nothing matches that means we need to pick up the paragraph -->
                <paragraph>
                    <xsl:value-of select=".//w:t" />
                </paragraph>
            </xsl:otherwise>
            </xsl:choose>
    </xsl:for-each>

它给出了输出(我在 XML 中创建了多个节点进行测试)

<Heading1>
    <paragraph> Paragraph1 </paragraph>
    <paragraph>table info </paragraph>
    <paragraph> Paragraph2 </paragraph>
    <paragraph> Paragraph3 </paragraph>

</Heading1>
<Heading1>
    <paragraph> Paragraph1 </paragraph>
    <paragraph>table info </paragraph>
    <paragraph> Paragraph2 </paragraph>
    <paragraph> Paragraph3 </paragraph>
</Heading1>
于 2011-12-28T17:07:34.467 回答
0

我怀疑您想要进行位置分组,对兄弟姐妹进行分组,并在满足某些条件时开始或结束一个组。如果这描述了问题,请查看将 xsl:for-each-group 与 group-starting-with 或 group-ending-with 属性一起使用。

于 2011-12-28T07:27:18.767 回答