【问题标题】:Xpath expression to access parent or sibling using HTML::TreeBuilder::XPath module使用 HTML::TreeBuilder::XPath 模块访问父级或兄弟级的 Xpath 表达式
【发布时间】:2011-10-13 23:16:25
【问题描述】:

我想使用 HTML::TreeBuilder::XPath Perl 模块选择节点的父节点或兄弟节点,让我们以如下示例 HTML 为例:

<tbody>
    <tr>
        <td class="c1">Match_Text</td>
        <td class="c2">Extact_Text</td>
    </tr>
    <tr>
        <td class="c1"></td>
        <td class="c2"></td>
    </tr>
</tbody>

所以我想为此提取文本“Match_Text”,我将 xpath 表达式为:

'/html/body//td[@class="c1"]="Match_Text"/../td[@class="c2"]'

这是我用例的有效表达式。

但看起来父级没有实现,我从 perl 模块收到以下错误:

轴axis_parent未实现[无法定位对象方法 “getParentNode”通过包“XML::XPathEngine::Literal”在 /usr/local/share/perl/5.10.1/XML/XPathEngine/Step.pm 第 326 行。]

任何人都可以建议一个可能适用于我的用例(访问节点的父/兄弟)的替代 Xpath 表达式。请注意,我只想使用 Xpath 表达式来执行此操作,并且不想创建 DOM 并显式遍历树。

【问题讨论】:

    标签: xml perl xpath


    【解决方案1】:

    错误信息具有误导性。问题不在于缺乏支持,而是您试图找到比较返回的布尔值的父级。它没有。

    你可以使用

    //*[ td[@class="c1" and text()="Match_Text"] ]/td[@class="c2"]
    
    //td[@class="c1" and text()="Match_Text"]/following-sibling::*
    
    //td[@class="c1" and text()="Match_Text"]/following-sibling::td[@class="c2"]
    
    //td[@class="c1" and text()="Match_Text"]/../td[@class="c2"]
    

    【讨论】:

    • XML::XPathEngine 将getChildNodes 实现为sub getChildNodes { return wantarray ? () : []; },所以它不会给你一个错误,即使得到一个litteral 的孩子是没有意义的。所以我可以添加具有相同内容的getParentNode,或者让它因错误而死(并对getChildNodesgetAttributes 执行相同的操作),这可能对用户更有帮助。对这个问题有什么看法?
    • @mirod,在我看来,带着有用的信息死去总比不匹配好。
    • 好的,我刚刚发布了一个在所有情况下都会死掉的新版本,并带有更好的错误消息。
    【解决方案2】:

    我以前从未见过任何这样的工作表达式。实际上,我认为错误是由于该表达式没有很好地组合和解析。

    无论如何,这里有两个替代方案可以实现您的目标——尽管没有使用指定的 Perl 模块进行测试:

    //td[@class="c1" and text()="Match_Text"]/../td[@class="c2"]
    //td[@class="c2" and ../td[@class="c1" and text()="Match_Text"]]

    shell-toolsonline-toolz 上测试。

    【讨论】:

      【解决方案3】:

      我想选择一个节点的父节点或兄弟节点 HTML::TreeBuilder::XPath Perl 模块。

      在任何情况下,如果您想要一个选择多个节点的 XPath 表达式,并且您知道其中每个节点都有一个单独的 XPath 表达式,您可以简单地使用标准 XPath 联合运算符|,如下所示:

       (/*/body//*[td[@class="c1"and . = 'Match_Text']])[1]
      |
        (/*/body//*[td[@class="c1"and . = 'Match_Text']])[1]
                     /td[[@class="c1"and not(. = 'Match_Text')]
      

      在这个 XPath 表达式中,| 运算符的第一个操作数是引用节点的父元素,联合运算符的第二个参数是一个表达式,它选择该父节点的所有子元素,其字符串值不同于参考节点的。

      结果是选择了两个节点集的并集。

      【讨论】:

        猜你喜欢
        • 2021-04-21
        • 1970-01-01
        • 2016-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多