【问题标题】:Xpath in docx, having parentheses as contains attributedocx中的Xpath,带有括号作为包含属性
【发布时间】:2015-01-29 19:36:13
【问题描述】:

使用用于 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 sn-p 可以在这里找到:https://gist.github.com/anonymous/6bd998117b1a493dbaf7

所以,我已经对其进行了调试,上面的 XPath 查询找到了 one 节点 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 行没有,我看到的唯一区别是括号......

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

【问题讨论】:

    标签: xml xpath openxml docx phpdocx


    【解决方案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() 造成任何麻烦。你在哪里读到的?

    【讨论】:

    • 感谢您的回答,请在此处找到更详细的代码示例:gist.github.com/anonymous/07eeddeb7d2f3c7db55b 第一个从第 16 行到第 74 行的“块”工作正常,而第 101 行到第 166 行则不行,并且我看到的唯一区别是括号...
    • @AdrianFöder 在这里单独运行没问题。不过有一点我没听懂:你说//w:p[w:r/w:t[text()[contains(.,"BLOCK_foo.bar(20).baz")]]]“没有按预期工作,但找到了两个节点”——这是什么意思?无论如何,您可以从 phpdocx 中显示一些代码吗?
    • 是的,它找到了两个节点(我通常期望的,因为有两次出现);但在它工作的情况下,它只找到一个节点。这就是我在这里不明白的......所以:工作:一个节点,不工作:两个节点。这是 phpdocx 的代码:i.imgur.com/yVtVq5U.png$affectedNodes.length 在错误情况下为 2,在运行中为 1。
    • @AdrianFöder 请不要链接到包含您的代码的图像。编辑问题并将其包含在其中。但不是作为图像,作为代码。
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2013-06-05
      • 1970-01-01
      • 2018-03-31
      • 2012-06-09
      • 2013-03-11
      • 1970-01-01
      • 2021-08-28
      • 2014-11-26
      • 2015-08-13
      相关资源
      最近更新 更多