【问题标题】:Selecting a deeply nested link using xpath query使用 xpath 查询选择深度嵌套的链接
【发布时间】:2011-08-11 17:28:06
【问题描述】:
<body class="en-us">   <div id="wrapper">
    <div id="content">
      <div class="content-top">
        <div class="content-bot">
          <div id="profile-wrapper" class=
          "profile-wrapper profile-wrapper-horde">
            <div class="profile-sidebar-anchor">
              <div class="profile-sidebar-outer">
                <div class="profile-sidebar-inner">
                  <div class="profile-sidebar-contents">
                    <div class="profile-sidebar-crest">
                      <a href="/wow/en/character/some-server/sometoon/" rel="np" class="profile-sidebar-character-model" style="">
                      </a>

                      <div class="profile-sidebar-info">
                        <div class="name">
                          <a href="/wow/en/character/some-server/sometoon/"
                          rel="np">Glitchshot</a>
                        </div>

                        <div class="under-name color-c8">
                          <span class="level"><strong>85</strong></span>
                          <a href="/wow/en/game/race/somerace" class="race">somerace</a> 
                          <a href="/wow/en/game/class/someclass" class="class">someclass</a>
                        </div>

                        <div class="guild">
                          <a href="/wow/en/guild/some-server/someguild/?character=sometoon">
                          Some Guild</a>
                        </div>

                        <div class="realm">
                          <span id="profile-info-realm" class="tip"
                          data-battlegroup="Stormstrike">Black
                          Dragonflight</span>
                        </div>
                      </div>
                    </div>

                    <ul class="profile-sidebar-menu" id="profile-sidebar-menu">
                      <li><a href=
                      "/wow/en/character/some-server/sometoon/" class=
                      "back-to" rel="np"><span class="arrow"><span class=
                      "icon">Character Summary</span></span></a></li>

                      <li class="root-menu"><a href=
                      "/wow/en/character/some-server/sometoon/achievement"
                         class="back-to" rel="np"><span class=
                         "arrow"><span class=
                         "icon">Achievements</span></span></a></li>

                      <li class=" active"><a href=
                      "/wow/en/character/some-server/sometoon/achievement#summary"
                         class="" rel="np"><span class="arrow"><span class=
                         "icon">Achievements</span></span></a></li>

                      <li class=""><a href=
                      "/wow/en/character/some-server/sometoon/achievement#92"
                         class="" rel="np"><span class="arrow"><span class=
                         "icon">General</span></span></a></li>

我知道我在这里发布了很多无用的代码,但希望你们了解一下 DOM 会是什么样子。

从这里:

<a href="/wow/en/character/some-server/sometoon/achievement#92" class="" rel="np"><span class="arrow"><span class="icon">General</span></span></a>

我想提取这个:

/wow/en/character/some-server/sometoon/achievement#92

来自已发布标记中的最后一个锚点。

我已经阅读了尽可能多的关于如何使用 xpath 查询来提取所需信息的内容,但我显然遗漏了一些东西。以下是我认为应该有效但无效的查询。

<?php
    $query = '*/ul[@class=profile-sidebar-menu]/ul/li[3]/ul/li[1]/a/@href';
    echo $query . "<br>";
    $achievementSubCategory = $xpath->query($query);

    $achiSubArray = array("URL" => $achievementSubCategory->item(0)->nodeValue);
    var_dump($achiSubArray);
    // Produces array(1) { ["URL"]=> NULL } which should look something more like:
    // array(1) { ["URL"]=> /wow/en/character/some-server/sometoon/achievement#92 }
?>

提前感谢您的帮助和建议

【问题讨论】:

  • 如果你知道它的格式,为什么你需要提取那个确切的链接?为什么不自己生成呢?
  • 我和@Dalton Conley 在一起。您可以使用 javascript 从 DOM 中轻松提取链接。
  • 我正在尝试从 wow 军械库中提取数据,我需要提取的数据的链接位于静态位置。我知道我可以使用 javascript 来实现这一点,但我正在尝试在服务器端进行,以消除对基本功能的 javascript 需求
  • 另外,我不需要那个链接,但如果我能拉出那个链接,那么我可以循环浏览后面的其余链接。基本上有几个类别是静态定位的。我将这些类别放在一个数组中,然后循环遍历提取子类别的类别。
  • 请显示您正在处理的所有 html。

标签: php xpath href


【解决方案1】:
*/ul[@class=profile-sidebar-menu]/ul/li[3]/ul/li[1]/a/@href

这个 XPath 表达式存在一些问题

  1. 它正在寻找一个 ul 元素,它是当前节点的 crandchild,并且具有名为 class 的属性,其字符串值等于其中一个子元素的字符串值ul,命名为profile-sidebar-menu。但是,ul 没有名为 profile-sidebar-menu 的子节点,并且整个表达式没有选择任何节点。

  2. 另一个问题是索引。 li[3] 选择第三个 li 元素 - 上下文节点的子元素。然而,想要的 a 元素是上下文节点的 fourth li 子元素的子元素。这必须表示为:li[4]。 XPath 位置是从 1 开始的,而不是从 0 开始的。

如果这两个问题得到纠正,我相信纠正后的表达式应该如下所示

*/ul[@class="profile-sidebar-menu"]/ul/li[4]/a/@href

从提供的 XML 文档的顶部元素 body 开始选择所需的 href 属性的绝对 XPath 表达式是:

/*/*/*/*/*/*/*/*/*/*/ul/li[4]/a/@href

以下是 XML 文档(提供的文档,通过添加一些缺少的结束标记使格式正确:

<body class="en-us">
    <div id="wrapper">
        <div id="content">
            <div class="content-top">
                <div class="content-bot">
                    <div id="profile-wrapper" class=
              "profile-wrapper profile-wrapper-horde">
                        <div class="profile-sidebar-anchor">
                            <div class="profile-sidebar-outer">
                                <div class="profile-sidebar-inner">
                                    <div class="profile-sidebar-contents">
                                        <div class="profile-sidebar-crest">
                                            <a href="/wow/en/character/some-server/sometoon/" rel="np" class="profile-sidebar-character-model" style=""></a>
                                            <div class="profile-sidebar-info">
                                                <div class="name">
                                                    <a href="/wow/en/character/some-server/sometoon/"
                              rel="np">Glitchshot</a>
                                                </div>
                                                <div class="under-name color-c8">
                                                    <span class="level">
                                                        <strong>85</strong>
                                                    </span>
                                                    <a href="/wow/en/game/race/somerace" class="race">somerace</a>
                                                    <a href="/wow/en/game/class/someclass" class="class">someclass</a>
                                                </div>
                                                <div class="guild">
                                                    <a href="/wow/en/guild/some-server/someguild/?character=sometoon">
                              Some Guild</a>
                                                </div>
                                                <div class="realm">
                                                    <span id="profile-info-realm" class="tip"
                              data-battlegroup="Stormstrike">Black
                              Dragonflight</span>
                                                </div>
                                            </div>
                                        </div>
                                        <ul class="profile-sidebar-menu" id="profile-sidebar-menu">
                                            <li>
                                                <a href=
                          "/wow/en/character/some-server/sometoon/" class=
                          "back-to" rel="np">
                                                    <span class="arrow">
                                                        <span class=
                          "icon">Character Summary</span></span>
                                                </a>
                                            </li>
                                            <li class="root-menu">
                                                <a href=
                          "/wow/en/character/some-server/sometoon/achievement"
                             class="back-to" rel="np">
                                                    <span class=
                             "arrow">
                                                        <span class=
                             "icon">Achievements</span></span>
                                                </a>
                                            </li>
                                            <li class=" active">
                                                <a href=
                          "/wow/en/character/some-server/sometoon/achievement#summary"
                             class="" rel="np">
                                                    <span class="arrow">
                                                        <span class=
                             "icon">Achievements</span></span>
                                                </a>
                                            </li>
                                            <li class="">
                                                <a href=
                          "/wow/en/character/some-server/sometoon/achievement#92"
                             class="" rel="np">
                                                    <span class="arrow">
                                                        <span class=
                             "icon">General</span></span>
                                                </a>
                                            </li>
                                        </ul>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>

可以通过使用the Xpath Visualizer 之类的工具对其进行评估来检查上述绝对 XPath 表达式是否准确选择了所需的 href 属性。

这是使用 XPath Visualizer 执行的选择的快照:

【讨论】:

  • 你是如何让这个 webapp 像这样显示文档的?
  • @Wes:你看答案了吗?有一个链接:“可以通过使用 Xpath Visualizer 之类的工具对其进行评估来检查上述绝对 XPath 表达式是否准确地选择了所需的 href 属性”。只需单击链接,然后单击两个“下载”图标之一。
  • @Wes:在这里,人们希望接受最好的答案。要接受答案,只需单击答案旁边的绿色复选标记。 :)
  • 谢谢兄弟,我确实阅读了,我想为你的答案投票,因为这是一个很好的答案,但它对我不起作用,因为我无法将我的文档加载到 webapp 中。您需要做些什么才能让它正确读取您的输入吗?
  • @Wes:当然,兄弟,缺少很多结束标签,我自己添加了它们(这在我的回答中提到)。您可以从我的答案中复制并粘贴已更正的 XML。
【解决方案2】:

如果你的 DOM 结构是一致的,那么类似下面的东西应该可以工作:

//ul[@class='profile-sidebar-menu']/li[last()]/a/@href

您的 xpath 语句毫无意义。您在路径中有多个 ul,但示例的结构并非如此。此外,xpath 中的索引从 1 开始,而不是 0。

【讨论】:

  • 我担心不发布所有的 html 会导致这种情况。有未知数量的链接将以与我发布的最后一个链接相同的方式显示。不过谢谢你的建议。使用循环增加
  • 元素的数量以获得下一个链接,直到没有更多。
  • 也许我误解了查询的操作方式。我认为 $query = '*/ul[@class=profile-sidebar-menu]/ul/li[3]/ul/li[1]/a/@href'; is = to $query = '*/ul[@class=profile-sidebar-menu]/ul/li/li/li/ul/li/li/a/@href';
  • 我在我的问题中犯了一个错误,没有发布足够的 HTML。我需要的实际链接后面还有另一个
  • li[3] 表示法表示在给定级别获得第 3 个 li。它不是指定深度的简写。
  • 好的,非常感谢。我尝试用适当深度的实际表示替换 li[3],例如 /li/li/li 等,但我仍然得到一个空数组。我不知所措。
  • 【解决方案3】:

    在上面显示的 html 的基础上(并假设最终标签已正确关闭),ewh'expression 应该可以正常工作。

    可能是你遗漏了文档的一些重要部分。尝试更具体:

    //ul[@class='profile-sidebar-menu' and @id='profile-sidebar-menu']/li/a[@href='/wow/en/character/some-server/sometoon/achievement#92']/@href

    我很确定它有效,通过 XPath Query Expression Tool 在线测试。

    如果您仍然没有得到结果,请尝试显示您正在处理的所有 html。

    【讨论】:

    • 这让我走上了仪式轨道。我不够宽敞,忽略了 id=。我认为不需要同时拥有它们。
    • 很好!请将此标记为答案,以便可以关闭线程。
    • 我会,除非这要求我知道 href 值是什么才能获得 href 值。我需要获取锚点的 href 值,这意味着我不知道 href 值。
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签