docx中的Xpath,括号为contains属性

时间:2015-01-29 19:36:13

标签: xml xpath openxml docx phpdocx

使用库进行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

第一个问题,诚然:为什么它只找到一个匹配但实际上有两个("起始"和#34;结束"块)。 此外,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,所以我最后认为表达式中的parantheses的出现是个问题?另一方面,contains()值用引号括起来,所以我说这不应该是一个问题;但我已经读过单引号也可能会在contains()表达式中遇到麻烦......

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

你知道我能在这做什么吗?

2 个答案:

答案 0 :(得分:1)

  

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

不,问题完全不同,它是以OOXML格式存储数据时MS Word的特性。内容随机分为单独的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>

字符串&#34; BLOCK_foo.bar&#34;正如预期的那样,在一个w:t元素中,在一个w:r元素内,但不是分成两半。这就是//w:p[w:r/w:t[text()[contains(.,"BLOCK_foo.bar")]]]仅返回一个w:p元素的原因。

对于你描述的这个其他块,我怀疑发生了同样的事情,但你没有显示代码,所以所有的赌注都已关闭。


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

答案 1 :(得分:0)

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

这是一个偷偷摸摸但又邪恶的正则表达式,它只是替换变量中的所有直到下一次出现变量,就像\$BLOCK_VARIABLE\$.+?\$BLOCK_VARIABLE\$一样。因此,每次出现的XML和内容都会被删除,并替换为$ VARIABLE $。

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