необходимо ли пространство имен документа XHTML для использования в XPATH - PullRequest
0 голосов
/ 30 мая 2011

Я очищаю некоторую веб-страницу для некоторых определенных частей веб-страницы. Я использую php, curl и xpath для получения раздела страницы. но люди предполагают, что я должен использовать namespaces документа XHTML для работы XPATHs. Насколько я знаю, namespaces используются, чтобы избежать коллизий между именами различных элементов, так зачем мне в этом случае namespaces? Я на самом деле конвертирую веб-страницу с помощью Tidy в XHTML. Нужны ли мне действительно пространства имен и, если да, то в каких случаях один и тот же код without namespaces хорошо работает для удаления содержимого из wikipedia. Также даже после изменения моего php-кода для включения namespaces код не работает для некоторых URL-адресов. Вы можете взглянуть на этот пост .

Ответы [ 2 ]

3 голосов
/ 30 мая 2011

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

Вам необходимо использовать префиксы пространств имен в выражениях XPath тогда и только тогда, когда обрабатываемый вами XML-документ использует пространства имен.

Во всех тестах имен XPath (1.0) используются квалифицированные имена, то есть выражения без префикса пространства имен всегда соответствуют только целям в пространстве без имен . Это означает, что выражение /element-1/element-2 всегда ищет элементы, которые не имеют определения пространства имен (другими словами: они принадлежат пространству без имен, другими словами: они имеют пустой URI пространства имен). Пример выражения XPath работает с этим документом ...

<element-1>
    <element-2>Works!</element-2>
</element-1>

... но этот документ не работает ...

<ns:element-1 xmlns:ns="http://example.com">
    <ns:element-2>Doesn't work</ns:element-2>
</ns:element-1>

... потому что в этом случае <element-1> и <element-2> принадлежат пространству имен (с URI http://example.com). Также обратите внимание, что элементы могут принадлежать пространству имен, даже если у них нет префикса пространства имен, если документ имеет пространство имен по умолчанию. Этот документ ...

<element-1 xmlns="http://example.com">
    <element-2>Similar to previous, and doesn't work either.</element-2>
</element-1>

... идентичен второму примеру документа, и использование XPath на нем также требует использования префиксов пространства имен.

Для поиска данных из этого документа потребуется зарегистрировать URI пространства имен с некоторым префиксом, а затем использовать этот префикс в выражениях XPath. Что-то вроде /px:element-1/px:element-2. Обратите внимание, что префикс, который вы регистрируете, не должен совпадать с тем, который используется в документе, но URI должны совпадать точно так же, как они. Еще один момент, на который следует обратить внимание: даже если элементы в пространстве имен по умолчанию не имеют префикса, вам все равно нужно использовать префикс, который вы определили в выражениях XPath, чтобы соответствовать им.

Так что необходимость в префиксе пространства имен в запросах XPath зависит от документа. Некоторые веб-сайты обслуживают свои страницы как допустимые документы XHTML, и, таким образом, все элементы принадлежат пространству имен XHTML. Некоторые другие сайты обслуживают HTML или XHTML без пространства имен, что является технически недопустимым XHTML.

Способ регистрации префиксов пространства имен зависит от используемой вами структуры XML или библиотеки. В php и SimpleXML это делается примерно так

$your_xml_doc->registerXPathNamespace("ns", "http://example.com");
$result = $your_xml_doc->xpath('/ns:element-1/ns:element-2');
1 голос
/ 31 мая 2011

Это возможно для использования выражений XPath, которые не используют пространства имен.

Если вы просматриваете веб-контент и не уверены, будет ли он XHTMLили правильно сформированный HTML, который не привязан к пространству имен, тогда вам может оказаться более удобным использовать более общий критерий соответствия для вашего XPath, который игнорирует пространство имен элементов.

Это можно сделать с помощьюуниверсальное соответствие для любого элемента (например, *), а затем используйте фильтр предикатов для local-name() элемента (например, *[local-name()='table']).

Это будет соответствовать любому элементу с таким именем, будь тооно привязано к определенному пространству имен или нет.

Например:

//*[local-name()='body']/*[local-name()='table'][4]
     /*[local-name()='tbody']/*[local-name()='tr'][3]
     /*[local-name()='td'][4]
...