0

使用用于 docx 操作的库 phpdocx.com,我偶然发现了一个我无法用我糟糕的 xpath 和 docx 知识解决的问题。

在 phpdocx 中有所谓的块变量,用于标记一个完整的块,例如

$BLOCK_foo.bar$
Here comes a value
$BLOCK_foo.bar$

为了定位和删除这些块,他们 (phpdocx) 使用以下 xpath 表达式:

//w:p[w:r/w:t[text()[contains(.,"BLOCK_foo.bar")]]]

可以在此处找到相应的 docx 片段:https ://gist.github.com/anonymous/6bd998117b1a493dbaf7

所以,我已经调试过了,上面的 XPath 查询找到了一个节点,w:p.

第一个问题,诚然:为什么它只找到一个匹配但实际上有两个(“开始”和“结束”块)。此外,由于那个书签东西,BLOCK_ 的出现被撕掉了。这到底是怎么回事?

但我的实际问题是,我有,不要问,像$BLOCK_foo.bar(20).baz$.

这个的 xpath 分别是

//w:p[w:r/w:t[text()[contains(.,"BLOCK_foo.bar(20).baz")]]]

这没有按预期工作,它找到了两个节点(w:p虽然都是);在哪里,我交叉检查了,

//w:p[w:r/w:t[text()[contains(.,"BLOCK_foo.bar20.baz")]]]

..正确地工作$BLOCK_foo.bar20.baz,所以我最后认为这是表达式中出现括号的问题?另一方面,该contains()值用引号引起来,所以我认为这不应该是问题;但我读过例如单引号也可能在contains()表达式中造成麻烦......

相关的 PHP 代码块是https://gist.github.com/anonymous/490418104fdf5cd1a791。可以在此处找到具体的 XML 示例,http ://gist.github.com/anonymous/07eeddeb7d2f3c7db55b 。从第 16 行到第 74 行的第一个“块”工作正常,而第 101 行到第 166 行没有,我看到的唯一区别是括号......

你知道我可以在这里做什么吗?

4

2 回答 2

1

所以我最后认为这是表达式中出现括号的问题?

不,问题完全不同,这是 MS Word 在以 OOXML 格式存储数据时的特性。内容被随机分成单独w:r的元素(所谓的“运行”)。正如你在这里看到的:

<w:r>
    <w:rPr>
        <w:rFonts w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/>
        <w:sz w:val="22"/>
        <w:szCs w:val="22"/>
        <w:lang w:val="en-US"/>
    </w:rPr>
    <w:t>$BLOCK_</w:t>
</w:r>
<w:bookmarkEnd w:id="1"/>
<w:r>
    <w:rPr>
        <w:rFonts w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/>
        <w:sz w:val="22"/>
        <w:szCs w:val="22"/>
        <w:lang w:val="en-US"/>
    </w:rPr>
    <w:t>foo.bar$</w:t>
</w:r>

正如预期的那样,字符串“BLOCK_foo.bar”不是在一个w:t元素中,在一个w:r元素中,而是分成两半。这就是为什么//w:p[w:r/w:t[text()[contains(.,"BLOCK_foo.bar")]]]只返回一个w:p元素。

对于您描述的另一个块,我怀疑会发生同样的情况,但是您没有显示代码,因此所有赌注都已取消。


顺便说一句,不,单引号一般不会造成contains()任何麻烦。你在哪里读到的?

于 2015-01-29T21:10:19.250 回答
0

好的,我发现了。括号实际上根本不是问题,我只是没有意识到 PHPDocx 如何处理块替换。

有一个狡猾但邪恶的正则表达式,它只是替换变量到下一次出现变量的所有内容,就像\$BLOCK_VARIABLE\$.+?\$BLOCK_VARIABLE\$. 因此,每一次出现的 XML 和东西都被删除,并用一次出现的 $VARIABLE$ 代替。

在下一步中,它通过 XPath 搜索变量的出现并删除父段落节点。

于 2015-02-02T16:42:03.590 回答