Разбор XPath объявлений пространства имен - PullRequest
1 голос
/ 11 августа 2011

Я использую XPath для извлечения только значений XML-элемента URL128. Их может быть много, хотя у меня есть только один в приведенном ниже примере. Когда я включаю xmlns = 'http://c1.net.corbis.com/' в элемент SearchResponse, я получаю пустой NodeList, но когда я удаляю этот элемент пространства имен, он работает нормально. Мне не хватает конфигурации?

String xmlData = "<SearchResponse xmlns='http://c1.net.corbis.com/'><searchResultDataXML><SearchResultData><SearchRequestUID Scope='Public' Type='Guid' Value='{cded773c-c4b7-4dd8-aaee-8e5b8b7a2475}'/><StartPosition Scope='Public' Type='Long' Value='1'/><EndPosition Scope='Public' Type='Long' Value='50'/><TotalHits Scope='Public' Type='Long' Value='323636'/></SearchResultData></searchResultDataXML><imagesXML><Images><Image><ImageUID Scope='Public' Type='Guid' Value='{a6f6d3e2-2c3f-4502-9741-eae2e1bb573a}'/><CorbisID Scope='Public' Type='String' Value='42-25763849'/><Title Scope='Public' Type='String' Value='Animals figurines'/><CreditLine Scope='Public' Type='String' Value='© Ocean/Corbis'/><IsRoyaltyFree Scope='Public' Type='Boolean' Value='True'/><AspectRatio Scope='Public' Type='String' Value='0.666667'/><URL128 Scope='Public' Type='String' Value='http://cachens.corbis.com/CorbisImage/thumb/25/76/38/25763849/42-25763849.jpg'/></Image></Images></imagesXML></SearchResponse>";
            InputSource source = new InputSource(new StringReader(xmlData));

            XPath xPath = XPathFactory.newInstance().newXPath();
            NodeList list = null;
            try {
                list = (NodeList) xPath.evaluate("//URL128/@Value", source, XPathConstants.NODESET);
            } catch (Exception ex) {
                System.out.println(ex.getMessage());
            }
            for (int i = 0; i < list.getLength(); i++) {
                System.out.println(list.item(i).getTextContent());
            }

Ответы [ 3 ]

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

Короче говоря, вам нужно предоставить NamespaceContext вашему XPath:

final XPath xPath = XPathFactory.newInstance().newXPath();
xPath.setNamespaceContext(new NamespaceContext() {
    @Override
    public Iterator<String> getPrefixes(final String namespaceURI) {
        return null;
    }
    @Override
    public String getPrefix(final String namespaceURI) {
        return null;
    }
    @Override
    public String getNamespaceURI(final String prefix) {
        return "http://c1.net.corbis.com/";
    }
});
final NodeList list = (NodeList) xPath.evaluate("//c:URL128/@Value", source, XPathConstants.NODESET);
for (int i = 0; i < list.getLength(); i++) {
    System.out.println(list.item(i).getTextContent());
}

Кажется, что единственный метод, который XPath требует от нас в этом случае реализоватьis getNamespaceURI(String prefix).

Обратите внимание, что фактический префикс в "c: URL128" на самом деле не имеет значения - вы могли бы так же легко использовать ": URL128".Когда у вас do есть несколько пространств имен в вашем XML, становится важно различать их (используя Map или серию if-then-else, если относительно мало элементов).

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

См. также в этом сообщении длябольше деталей.

1 голос
/ 08 сентября 2012

Для этого есть несколько более простое решение, которое не предполагает размещения жестко закодированных ссылок URI в вашем коде ... Просто проанализируйте документ с атрибутом осведомленности о пространстве имен, установленным в false ...

String xmlData = "<SearchResponse xmlns='http://c1.net.corbis.com/'><searchResultDataXML><SearchResultData><SearchRequestUID Scope='Public' Type='Guid' Value='{cded773c-c4b7-4dd8-aaee-8e5b8b7a2475}'/><StartPosition Scope='Public' Type='Long' Value='1'/><EndPosition Scope='Public' Type='Long' Value='50'/><TotalHits Scope='Public' Type='Long' Value='323636'/></SearchResultData></searchResultDataXML><imagesXML><Images><Image><ImageUID Scope='Public' Type='Guid' Value='{a6f6d3e2-2c3f-4502-9741-eae2e1bb573a}'/><CorbisID Scope='Public' Type='String' Value='42-25763849'/><Title Scope='Public' Type='String' Value='Animals figurines'/><CreditLine Scope='Public' Type='String' Value='© Ocean/Corbis'/><IsRoyaltyFree Scope='Public' Type='Boolean' Value='True'/><AspectRatio Scope='Public' Type='String' Value='0.666667'/><URL128 Scope='Public' Type='String' Value='http://cachens.corbis.com/CorbisImage/thumb/25/76/38/25763849/42-25763849.jpg'/></Image></Images></imagesXML></SearchResponse>";
InputSource source = new InputSource(new StringReader(xmlData));

// create doc instance instead of passing source straight to XPath...
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false); // must be false
DocumentBuilder builder = factory.newDocumentBuilder();
final Document doc = builder.parse(source);

XPath xPath = XPathFactory.newInstance().newXPath();

// use doc instead
NodeList list = (NodeList) xPath.evaluate("//URL128/@Value", doc, 
        XPathConstants.NODESET);

for (int i = 0; i < list.getLength(); i++) {
    System.out.println(list.item(i).getTextContent());
}
0 голосов
/ 11 августа 2011

ниже - два способа реализации того, что наметил AlistairIsreal:

при использовании Spring вы можете положиться на интерфейс org.springframework.util.xml.SimpleNamespaceContext.

InputSource source = new InputSource(new StringReader(unescaped));

            XPath xPath = XPathFactory.newInstance().newXPath();
            NodeList list = null;
            try
            {
                SimpleNamespaceContext nsCtx = new SimpleNamespaceContext();
                nsCtx.bindNamespaceUri("ns", "http://c1.net.corbis.com/");
                xPath.setNamespaceContext(nsCtx);
                list = (NodeList) xPath.evaluate("//ns:URL128/@Value", source, XPathConstants.NODESET);
            } catch (Exception ex)
            {
                System.out.println(ex.getMessage());
            }
            for (int i = 0; i < list.getLength(); i++)
            {
                System.out.println(list.item(i).getTextContent());
            }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...