Результаты XPath в пустую строку - PullRequest
6 голосов
/ 26 августа 2011

Ниже приведен мой XML-файл

<xyzevent xmlns="http://www.xyz.com/common/xyzevent/v1" xmlns:xsi="http://www.w3.org2001XMLSchema-instance">
<header>
 ----
</header>
<subscription xmlns="http://www.xyz.com/common/xyzevent/source/v1">
  <sender></sender>
  <receiver>
    <clientsubscription>
        <servicemap>nanna</servicemap>
    </clientsubscription>
  </receiver>
</subscription> 
</xyzevent>

Когда я создаю документ org.w3c.dom.Document из этого XML и применяю XPathExperssion с выражением

/xyzevent/subscription/receiver/clientsubscription/servicemap/text()

, получается пустая строка.В чем может быть проблема с выражением?

Спасибо

Ответы [ 4 ]

7 голосов
/ 26 августа 2011

Это потому, что ваш XML-документ использует пространство имен.XPath действительно раздражает пространства имен.Чтобы убедиться в этом, удалите два xmlns=http://.../v1 из документа и снова запустите выражение XPath, в котором не размеченный, непроверяемый XML-файл.Это будет соответствовать.

То, что происходит, заключается в том, что ваше выражение XPath пытается выбрать /xyzevent, когда ваш документ содержит {http://.../v1}:xyzevent, что не одно и то же.

Существуют различные способывокруг этой проблемы.Надлежащим способом является установка NamespaceContext, чтобы вы могли использовать нотацию prefix:localName в выражении XPath и разрешить префиксы в правильном URI.В xerces docs и некоторых других в других местах StackOverflow есть небольшая реклама.Подробное описание на ibm.com .

. В вашем NamespaceContext будет содержаться два (или более) сопоставления:

{
    event => http://www.xyz.com/common/xyzevent/v1
    source => http://www.xyz.com/common/xyzevent/source/v1
}

Тогда ваше выражение XPath может стать /event:xyzevent/source:subscription/source:receiver/.../text().

В качестве обходного решения , неприятного , вы можете переписать выражение xpath для выбора с помощью функции local-name():

/*[local-name()='xyzevent']/*[local-name()='subscription'/ ...

В этом случае выражениесоответствует любому элементу, локальное имя которого xyzevent, независимо от URI пространства имен.

2 голосов
/ 26 августа 2011

Ваш XML имеет пространство имен по умолчанию: xmlns="http://www.xyz.com/common/xyzevent/v1", поэтому вам нужно определить его в вашем движке XML / XPath.

Или использовать этот XPath:

/*[local-name() = 'xyzevent']
    /*[local-name() = 'subscription']
        /*[local-name() = 'receiver']
            /*[local-name() = 'clientsubscription']
                /*[local-name() = 'servicemap']
                    /text()
1 голос
/ 26 августа 2011

Я оценил ваше выражение по следующей ссылке:

http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm

И, похоже, он выбирает "нанна".

1 голос
/ 26 августа 2011

xyzevent является вашим корневым элементом, поэтому вам просто нужно использовать "/subscription/receiver/clientsubscription/servicemap/text()".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...