Почему я не могу получить содержимое тега с помощью XPath в методе Java?

Я очень новичок в XPath, и у меня есть следующая проблема:

У меня есть метод Java, который получает данные от веб-сервисов, и эти данные находятся в XML-документе, поэтому мне нужно использовать XPath, чтобы получить определенное значение внутри этого результирующего XML-документа.

В частности, у меня есть весь вывод XML, предоставленный моей веб-службой (ответ веб-службы):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <getConfigSettingsResponse xmlns="http://tempuri.org/">
         <getConfigSettingsResult><![CDATA[<root>
                        <status>
                            <id>0</id>
                            <message></message>
                        </status>

<drivers>
<drive id="tokenId 11">
  <shared-secret>Shared 11</shared-secret>
  <encoding>false</encoding>
  <compression />
</drive>
<drive id="tokenId 2 ">
  <shared-secret>Shared 2  </shared-secret>
  <encoding>false</encoding>
  <compression>false</compression>
</drive>
</drivers>
</root>]]></getConfigSettingsResult>
      </getConfigSettingsResponse>
   </s:Body>
</s:Envelope>

Теперь в классе Java я выполняю следующие операции:

XPath xPath;                        // An utility class for performing XPath calls on JDOM nodes

Element objectElement;              // An XML element
                        //xPath = XPath.newInstance("s:Envelope/s:Body/getVersionResponse/getVersionResult");

            try {
                // XPath selection:
                xPath = XPath.newInstance("s:Envelope/s:Body");
                xPath.addNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
                objectElement = (Element) xPath.selectSingleNode(documentXML);

                if (objectElement != null) {
                    result = objectElement.getValue();
                    System.out.println("RESULT:");
                    System.out.println(result);
                }
            } catch (JDOMException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

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

RESULT:
<root>
                        <status>
                            <id>0</id>
                            <message></message>
                        </status>

<drivers>
<drive id="tokenId 11">
  <shared-secret>Shared 11</shared-secret>
  <encoding>false</encoding>
  <compression />
</drive>
<drive id="tokenId 2 ">
  <shared-secret>Shared 2  </shared-secret>
  <encoding>false</encoding>
  <compression>false</compression>
</drive>
</drivers>
</root>

Теперь моя проблема заключается в том, что я хочу получить доступ только к содержимому тега 0, поэтому я хочу, чтобы (в данном случае) моя переменная result содержала >0 значение.

Но я не могу, я попытался изменить предыдущий выбор XPath с помощью:

xPath = XPath.newInstance("s:Envelope/s:Body/s:status/s:id");

Но поступая таким образом, я получаю, что мой objectElement равен null.

Почему? Что мне не хватает? Что мне нужно сделать, чтобы переменная результата mu содержала содержимое тега id?

Tnx

Андреа


person AndreaNobili    schedule 21.11.2013    source источник
comment
Вы используете JDOM 1.x или 2.x?   -  person rolfl    schedule 21.11.2013


Ответы (2)


Ваш "корневой" узел в разделе "CDATA". Весь раздел интерпретируется как текст, и вы не можете искать его по xPath. Вы можете получить текст из «objectElement.getValue()», проанализировать его как новый XML, а затем получить значение тега «id» с новым xPath. Также вы можете искать "objectElement.getValue()" для значения тега "id" с регулярным выражением.

person pasha701    schedule 21.11.2013
comment
ммм, что вы имеете в виду, когда говорите мне, что мой корневой узел находится в разделе CDATA? - person AndreaNobili; 21.11.2013
comment
и что мне нужно сделать, чтобы разобрать его как новый XML? - person AndreaNobili; 21.11.2013
comment
Вы можете увидеть ‹![CDATA[‹root› в вашем XML. Подробнее о CDATA здесь: w3schools.com/xml/xml_cdata.asp Вы можете проанализировать text из objectElement.getValue() таким же образом, как при анализе всего документа ‹s:Envelope. - person pasha701; 21.11.2013
comment
С точки зрения вашего DOM весь блок внутри ‹![CDATA[...]› представляет собой просто фрагмент текста. Вы можете взять этот кусок и проанализировать его как XML, а затем вы сможете запустить на нем XPath. - person hcayless; 21.11.2013
comment
@hcayless хорошо, но что мне нужно сделать, чтобы взять этот кусок текста и проанализировать его как XML? - person AndreaNobili; 21.11.2013

На самом деле вы должны использовать новый XPathAPI в JDOM 2.x и принять во внимание ответ pasha701, ваш код должен выглядеть примерно так:

Namespace soap = Namespace.getNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
Namespace tempuri = Namespace.getNamespace("turi", ""http://tempuri.org/");
XPathExpression<Element> xpath = XPathFactory.instance().compile(
       "s:Envelope/s:Body/turi:getConfigSettingsResponse/turi:getConfigSettingsResult",
       Filters.element(), null, soap, tempuri);
Element result = xpath.evaluateFirst(documentXML);
String resultxml = result.getValue();
Document resultdoc = new SAXBuilder().build(new StringReader(resultxml));
Element id = resultdoc.getRootElement().getChild("status").getChild("id");
person rolfl    schedule 21.11.2013