【问题标题】:Extract text from Word-Document using XSLT使用 XSLT 从 Word 文档中提取文本
【发布时间】:2019-12-16 16:54:11
【问题描述】:

我必须使用 XSLT 从 Word 文档中提取段落(意味着:标题及其内容)。我已经分析了结构,并且可以使用 XSLT 到达 .docx 文件中的必要节点。但是现在我不知道如何在标题之间对w:t-tags 的内容进行分组,因为 Word 以一种非常奇怪的方式分割文本。

输入数据如下:

<w:body xmlns:w="somenamespace">
   <w:p>
      <w:pPr> <w:pStyle w:val="Heading1" /> </w:pPr>
      <w:r> <w:t>My Headl</w:t> </w:r>
      <w:r> <w:t>ine</w:t> </w:r>
   </w:p>
   <w:p>
      <w:r> <w:t>text 1.1.1 </w:t> </w:r>
      <w:r> <w:t>text 1.1.2 </w:t> </w:r>
   </w:p>
   <w:p>
      <w:r> <w:t>text 1.2.1 </w:t> </w:r>
      <w:r> <w:t>text 1.2.2 </w:t> </w:r>
   </w:p>
   <w:p>
      <w:pPr> <w:pStyle w:val="Heading1" /> </w:pPr>
      <w:r> <w:t>My seco</w:t> </w:r>
      <w:r> <w:t>nd Headline</w:t> </w:r>
   </w:p>
   <w:p>
      <w:r> <w:t>text 2.1.1 </w:t> </w:r>
      <w:r> <w:t>text 2.1.2 </w:t> </w:r>
   </w:p>
   <w:p>
      <w:r> <w:t>text 2.2.1 </w:t> </w:r>
      <w:r> <w:t>text 2.2.2 </w:t> </w:r>
   </w:p>
</w:body>

连接单个段落的内容是没有问题的。所以很容易将数据合并成一个紧凑的结构,如下所示:

<Document>
    <Paragraphs>
        <Headline>My Headline</Headline>
        <Content>text 1.1.1 text 1.1.2 </Content>
        <Content>text 1.2.1 text 1.2.2 </Content>
        <Headline>My second Headline</Headline>
        <Content>text 2.1.1 text 2.1.2 </Content>
        <Content>text 2.2.1 text 2.2.2 </Content>
    </Paragraphs>
</Document>

但是这种结构并不总是有用的,因为它仍然没有一个 xml 元素来表示一个段落的内容。 那么有谁知道如何合并代表标题的w:p-元素之间的所有段落? 我想要一个将w:body-content 转换为如下结构的 XSLT:

<Document>
    <Paragraph>
        <Headline>My Headline</Headline>
        <Content>text 1.1.1 text 1.1.2 text 1.2.1 text 1.2.2 </Content>
    </Paragraph>
    <Paragraph>
        <Headline>My second Headline</Headline>
        <Content>text 2.1.1 text 2.1.2 text 2.2.1 text 2.2.2 </Content>
    </Paragraph>
</Document>

我发现了什么:

  • 如果w:p-元素包含w:pPr-元素,则它始终是此w:p-元素的第一个子节点

  • 如果w:p-元素在此条件下匹配./w:pPr/w:pStyle[@w:val='Heading1']&gt;,则此w:p-元素中的所有w:r-元素都属于该段落的标题。

【问题讨论】:

    标签: xml xslt openxml


    【解决方案1】:

    这可能是您问题的解决方案。您需要在 xslt 中使用for-each-group 语句。您可以匹配整个w:p 元素并定义组的第一个元素是定义标题样式的w:p。之后,您可以使用 current-group 函数获取项目,该函数为您提供组的 while 节点数组。

    XSLT:

    <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:w="somenamespace">
      <xsl:output method="xml" omit-xml-declaration="yes" />
    
    
      <xsl:template match="w:body">
        <Document>
          <xsl:for-each-group select="w:p" group-starting-with="*[./w:pPr/w:pStyle[@w:val='Heading1']]">
                <xsl:element name="Paragraph">
                    <xsl:element name="Headline">
                        <xsl:value-of select="current-group()[1]/*/w:t/text()" />
                    </xsl:element>
                    <xsl:element name="Content">
                        <xsl:for-each select="current-group()[position()>1]/*">
                                <xsl:copy-of select="./w:t/text()" />
                        </xsl:for-each>
                    </xsl:element>
                </xsl:element>
          </xsl:for-each-group>
        </Document>
      </xsl:template>
    
      <xsl:template match="*|node()">
        <xsl:apply-templates />
      </xsl:template>
    </xsl:stylesheet>
    

    输出:

    <Document xmlns:w="somenamespace">
      <Paragraph>
        <Headline>My Headline</Headline>
        <Content>text 1.1.1 text 1.1.2 text 1.2.1 text 1.2.2 </Content>
      </Paragraph>
      <Paragraph>
        <Headline>My second Headline</Headline>
        <Content>text 2.1.1 text 2.1.2 text 2.2.1 text 2.2.2 </Content>
      </Paragraph>
    </Document>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      相关资源
      最近更新 更多