XSLT:找到所选元素上方的第一个元素

XSLT: find first element above selected element

我想获取 docx 中 table 之前的第一个标题 (h1)。

我可以获得所有标题:

<xsl:template match="w:p[w:pPr/w:pStyle[@w:val='berschrift1']]">
    <p>
        <context>
            <xsl:value-of select="." />
        </context>
    </p>
</xsl:template>

我也可以获得所有 tables

<xsl:template match="w:tbl">
    <p>
    <table>
        <xsl:value-of select="." />
    </table>
    </p>
</xsl:template>

可惜处理器不接受

<xsl:template match="w:tbl/preceding-sibling::w:p[w:pPr/w:pStyle[@w:val='berschrift1']]">
    <p>
    <table>
        <xsl:value-of select="." />
    </table>
    </p>
</xsl:template>

这是从 docx 中提取的精简 XML 文件:http://pastebin.com/KbUyzRVv 结果我想要这样的东西:

<context>Let’s get it on</context> <- my heading
<table>data</table>

<context>Let’s get it on</context> <- my heading
<table>data</table>

<context>We’re in the middle of something</context> <- my heading
<table>data</table>

多亏了 Daniel Haley,我才能够找到解决该问题的方法。我将 post 放在这里,所以它独立于我 post 下面的 pastebin。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
  xmlns:v="urn:schemas-microsoft-com:vml" exclude-result-prefixes="xsl w v">
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="w:tbl">
            <context>
                <xsl:value-of select="(preceding-sibling::w:p[w:pPr/w:pStyle[@w:val = 'berschrift1']])[last()]"/>
            </context>
            <table>
                <xsl:value-of select="."/>
            </table>
    </xsl:template>
    <xsl:template match="text()"/>
</xsl:stylesheet>

没有 Minimal, Complete, and Verifiable example 很难回答,但试试这个:

<xsl:template match="w:tbl">
  <p>
    <table>
      <xsl:value-of select="(preceding::w:p[w:pPr/w:pStyle[@w:val='berschrift1']])[last()]"/>
    </table>
  </p>
</xsl:template>

假设您可以使用 XSLT 2.0(现在大多数人都可以),我在这里发现一个有用的技术是使用一个全局变量来选择所有相关节点:

<xsl:variable name="special" 
  select="//w:tbl/preceding-sibling::w:p[w:pPr/w:pStyle[@w:val='berschrift1']][1]"/>

然后在模板规则中使用这个变量:

<xsl:template match="w:p[. intersect $special]"/>

在 XSLT 3.0 中,您可以将其减少为

<xsl:template match="$special"/>