使用XSLT从Word文档中提取文本

时间:2019-12-16 16:54:11

标签: xml xslt openxml

我必须使用XSLT从Word文档中提取段落(意味着:标题及其内容)。我已经分析了结构,并可以使用XSLT到达.docx文件中的必要节点。但是现在我不知道如何在标题之间对w:t标签的内容进行分组,因为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元素的之间合并所有段落? 我想要一个XSLT,它可以将w:body-内容转换为类似这样的结构:

<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']>元素,则该w:r元素中的所有w:p元素都属于该段落的标题。

1 个答案:

答案 0 :(得分: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>