使用库进行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 ......
你知道我能在这做什么吗?
答案 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)
这是一个偷偷摸摸但又邪恶的正则表达式,它只是替换变量中的所有直到下一次出现变量,就像\$BLOCK_VARIABLE\$.+?\$BLOCK_VARIABLE\$
一样。因此,每次出现的XML和内容都会被删除,并替换为$ VARIABLE $。
在下一步中,它通过XPath搜索变量的出现并删除父段落节点。