#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:
-
Выполняется поиск
ul
элемента, который является дочерним элементом текущего узла и который имеет атрибут с именем,class
строковое значение которого равно строковому значению одного из дочерних элементовul
, namedprofile-sidebar-menu
. Однако уul
нет имен дочерних элементовprofile-sidebar-menu
, и все выражение не выбирает какой-либо узел. -
Другой проблемой является индексация.
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.