Nano Hash - криптовалюты, майнинг, программирование

Почему этот базовый селектор XPath не работает

Вот моя основная структура:

<div id="PrimaryContentBlock">
    <form>
         ......

Я пытаюсь выбрать элементы внутри формы, но XPath не находит ничего, кроме div-элемента primarycontentblock.

Первый запрос находит родительский узел, а второй ничего не находит.

$dom->query('//*[@id="PrimaryContentBlock"]');
$dom->query('//*[@id="PrimaryContentBlock"]/form');

Есть идеи, почему XPath ведет себя так странно? Я видел много непоследовательного поведения при работе с запросами DOMXPath.

10.02.2014

  • у вас могут быть проблемы с пространствами имен. Проверьте, упоминается ли в вашей структуре пространство имен по умолчанию (что-то вроде xmlns=...) 10.02.2014
  • Не могли бы вы показать больше вашей структуры HTML? Откуда вы это взяли? 10.02.2014

Ответы:


1

Это может произойти, например, если у вас есть XHTML-документ (с декаларацией xmlns в корневом элементе html) и вы анализируете его как XML. В таком документе все элементы являются частью пространства имен http://www.w3.org/1999/xhtml, и вам нужно указать это при запросе.

Ваш первый запрос, //*[@id="PrimaryContentBlock"], найдет любой элемент с соответствующим атрибутом id, в том числе в пространстве имен XHTML (именно это означает *). Второй запрос, //*[@id="PrimaryContentBlock"]/form, ищет form элементов, которых нет ни в одном пространстве имен. Это не соответствует документу, поскольку все элементы form находятся в пространстве имен XHTML по умолчанию.

Самый простой способ исправить это, если это XHTML-документ, — проанализировать его как HTML. Если вы сейчас делаете что-то вроде:

$domdocument->loadXML(...);

измените его на использование loadHTML:

$domdocument->loadHTML(...);

Если вы хотите проанализировать документ как XML, вам нужно указать пространство имен в запросе. Сначала вам нужно зарегистрировать URI и префикс пространства имен, который вы собираетесь использовать с экземпляром DOMXPath, затем измените свой запрос, чтобы включить новый префикс:

$xpath = new DOMXPath($doc);
$xpath->registerNamespace('xhtml', "http://www.w3.org/1999/xhtml");

$result = $xpath->query('//*[@id="PrimaryContentBlock"]/xhtml:form')
10.02.2014
  • Попробуйте это //*[@id="PrimaryContentBlock"]/*[local-name()='form']. Если это работает, то это проблема пространства имен. 10.02.2014
  • Спасибо, Мэтт и Любурк, за подсказки по пространству имен. Я подозреваю, что пространство имен может быть виновато в некоторых несоответствиях, с которыми я сталкивался. Эта текущая ошибка была вызвана моей собственной оплошностью. Я создал исходный объект XPath для предыдущего документа, но не сбрасывал XPath для DOM нового документа, который пытался запросить. 11.02.2014

  • 2

    Учитывая, что у вас есть вышеуказанная структура, и вы уверены, что документ правильно сформирован, оба ваших запроса БУДУТ работать:

    $xml = <<<EOF
    <div id="PrimaryContentBlock">
        <form></form>
    </div>
    EOF;
    
    $doc = new DOMDocument();
    $doc->loadHTML($xml);
    $selector = new DOMXPath($doc);
    
    foreach($selector->query('//*[@id="PrimaryContentBlock"]/form') as $element) {
        echo $element->nodeName;
    }
    

    Выход:

    form
    

    Если для вас верно следующее предложение:

    Я видел много непоследовательного поведения при работе с запросами DOMXPath.

    ... то у вас либо недостаточно опыта работы с XPath, либо ваши входные данные сформированы неправильно. По крайней мере, одна из этих двух причин применима ко мне, когда у меня возникают проблемы с определенным запросом.

    10.02.2014
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..