Выбор глубоко вложенной ссылки с помощью запроса xpath

#php #xpath #href

#php #xpath #href

Вопрос:

 <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 }
?>
  

Заранее благодарю вас за вашу помощь и советы

Комментарии:

1. Зачем вам нужно извлекать именно эту ссылку, если вы знаете ее формат? Почему бы не сгенерировать ее самостоятельно?

2. Я с @Dalton Conley. Вы можете легко извлекать ссылки с помощью javascript из DOM.

3. Я пытаюсь извлечь данные из wow armory, ссылки на данные, которые мне нужно извлечь, расположены в статическом положении. Я понимаю, что могу выполнить это с помощью javascript, но пытаюсь сделать это на стороне сервера, чтобы устранить необходимость в javascript для обеспечения необходимой функциональности

4. Кроме того, мне нужна не только эта ссылка, но если я смогу извлечь ее, то смогу просмотреть остальные ссылки, которые следуют. В принципе, существует несколько категорий, которые расположены статически. Я помещаю эти категории в массив, затем перебираю категории, извлекая подкатегории.

5. Пожалуйста, покажите весь html, над которым вы работаете.

Ответ №1:

 */ul[@class=profile-sidebar-menu]/ul/li[3]/ul/li[1]/a/@href
  

Есть несколько проблем с этим выражением XPath:

  1. Выполняется поиск ul элемента, который является дочерним элементом текущего узла и который имеет атрибут с именем, class строковое значение которого равно строковому значению одного из дочерних элементов ul , named profile-sidebar-menu . Однако у ul нет имен дочерних элементов profile-sidebar-menu , и все выражение не выбирает какой-либо узел.

  2. Другой проблемой является индексация. li[3] выбирает третий li дочерний элемент контекстного узла. Однако требуемый a элемент является дочерним по отношению к четвертому li дочернему элементу контекстного узла. Это должно быть выражено как: li[4] . Позиции XPath основаны на 1, а не на 0.

Если эти две проблемы будут исправлены, я полагаю, что исправленное выражение должно выглядеть следующим образом:

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

Абсолютное выражение XPath, которое выбирает требуемый href атрибут, начиная с верхнего элемента body предоставленного XML-документа, является:

 /*/*/*/*/*/*/*/*/*/*/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>
  

Можно проверить, что приведенное выше абсолютное выражение XPath точно выбирает требуемый href атрибут, оценив его с помощью такого инструмента, как визуализатор Xpath.

Вот снимок выбора, выполненный с помощью визуализатора XPath:

введите описание изображения здесь

Комментарии:

1. Как вы заставили это веб-приложение отображать документ таким образом?

2. @Wes: Ты прочитал ответ? Есть ссылка: «Можно проверить, что приведенное выше абсолютное выражение XPath точно выбирает требуемый атрибут href, оценив его с помощью инструмента, подобного Xpath Visualizer». Просто нажмите на ссылку, а затем на один из двух значков «загрузить».

3. @Wes: Здесь, на SO, ожидается, что вы примете лучший из ответов. Чтобы принять ответ, просто нажмите на зеленую галочку рядом с ответом. 🙂

4. Спасибо, братан, я прочитал, и я хотел бы проголосовать за твой ответ, потому что это хороший ответ, но у меня он не сработал, потому что я не могу загрузить свой документ в веб-приложение. Было ли что-нибудь, что вам нужно было сделать, чтобы заставить его правильно прочитать ваш ввод?

5. @Wes: Конечно, братан, отсутствовало много конечных тегов, и я добавил их сам (об этом упоминается в моем ответе). Вы можете просто скопировать и вставить уже исправленный XML из моего ответа.

Ответ №2:

Если ваша структура DOM согласована, то должно сработать что-то вроде следующего:

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

Ваше утверждение xpath не имеет смысла. У вас есть несколько ul в пути, но образец не структурирован таким образом. Кроме того, индексация в xpath начинается с 1, а не с 0.

Комментарии:

1. Я боялся, что не публикация всего html приведет к этому. Существует неизвестное количество ссылок, которые будут отображаться таким же образом, как последняя ссылка, которую я опубликовал, отображалась как. Тем не менее, спасибо за ваше предложение. Используя цикл, увеличивайте количество элементов <li>, чтобы получить следующую ссылку, пока их не останется.

2. Возможно, я неправильно понял, как выполняется запрос. Я думаю, что $query = ‘*/ul[@class=profile-sidebar-menu]/ul/li[3]/ul/li[1]/a/@href’; является = к $query = ‘*/ul[@class=profile-sidebar-menu]/ul/li/li/li/ul/li/li/a /@href’;

3. Я допустил ошибку в своем вопросе, разместив недостаточно HTML. Есть еще <ul> и некоторые <li>, которые следуют за фактической ссылкой, которая мне нужна. [ссылка] us.battle.net/wow/en/character/black-dragonflight/rustrazor/… вы попадете на страницу, которую я просматриваю. Мне нужно иметь возможность получать ссылки, которые ведут на «Easter Kingdoms», «Kalimdor» и т.д. И т.п.

4. В нотации li [3] указано, что нужно получить 3-й li на заданном уровне. Это не сокращение для указания глубины.

5. Хорошо, большое вам спасибо. Я попытался заменить 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, над которым вы работаете.

Комментарии:

1. Это навело меня на след rite. Я не был достаточно пространным и пропускал id = . Я не думал, что требуется иметь их оба.

2. Отлично! Пожалуйста, отметьте это как ответ, чтобы поток мог быть закрыт.

3. Я бы хотел, за исключением того, что для этого требуется, чтобы я знал, каково значение href, чтобы получить значение href. Мне нужно получить значение href привязки, чтобы это означало, что я не знаю значение href.