使用XPath提取多个相关节点

时间:2011-07-19 00:08:56

标签: php xpath

显示的XML是我正在使用的简化版本。我正在使用PHP,DOMDocument和DOMXPath。

我有许多相似的节点彼此相邻,但孩子们略有不同。鉴于我可以根据子节点的内容找到其中一个节点,我如何使用XPath来获取前一节点,最初选择的节点,后续节点以及后面两个位置的后续节点。

以下是XML示例:

<w:p>        
    <w:r>
        <w:rPr>...</w:rPr>
        <w:t>Text</w:t>
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="begin" />
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:instrText> MERGEFIELD  [PatName]  \* MERGEFORMAT  </w:instrText>
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="separate" />
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:t>[PatName]</w:t>
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="end" />
    </w:r>
</w:p>

要使用的起始节点是w:instrText节点,XPath看起来像:

//w:r[contains(w:instrText,'MERGFIELD [PatFirstName]')].

然后我可以使用前一个兄弟轴来定位前一个项目。 XPath看起来像:

//w:r[contains(w:instrText,'MERGFIELD [PatFirstName]')]/preceding-sibling::w:r[1].

然后我想抓住包含w:instrText的原始w:r,以及包含w:fldChar的其余两个w:r节点,使w:t节点离开选择。但是我为此编写XPath的尝试已经解开了:

//w:r[contains(w:instrText,'MERGEFIELD  [PatFirstName]')]/preceding-sibling::w:r[1]/following-sibling::w:r[1 and 2] 

抓取太多节点,可能是因为原始包含的条件不适用于以下兄弟条件。)

最终,将从该代码段中提取以下条目。

    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="begin" />
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:instrText> MERGEFIELD  [PatName]  \* MERGEFORMAT  </w:instrText>
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="separate" />
    </w:r>
    <w:r>
        <w:rPr>...</w:rPr>
        <w:fldChar w:fldCharType="end" />
    </w:r>

将相对节点用于搜索非常重要,因为XML中可能存在其他类似的节点组合。

有些人可能会将此XML视为合并域的Word 2003 XML格式,其中大部分内容已被删除。我正在尝试隔离包含w:t的w:r节点,因此我可以更新它,并删除用于将其标识为合并域的周围节点。

1 个答案:

答案 0 :(得分:0)

我得出的结论是,我所要求的仅仅是XPath过于雄心勃勃。跟随兄弟和前兄弟轴是1或所有交易(除非有人可以告诉我)。

我最终使用XPath来获取我有兴趣替换的w:t节点,基于MERGEFIELD,然后我走DOM,使用PHP中的DOMDocument删除其他节点。

这是我最终使用的XPATH,表示为PHP中变量的赋值。

$query = '//w:r[preceding-sibling::w:r[2][contains(w:instrText,\'MERGEFIELD  '.$mergeField.'\')]]/w:t';