Разбор XML с использованием Java - PullRequest
1 голос
/ 30 января 2012

Я пытаюсь разобрать элемент dom.

Элемент элемента:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://X/feed2</id>
  <title>Sample Feed</title>
  <entry>
    <id>http://X/feed2/104</id>
    <title>New Title</title>
  </entry>
</feed>

Я пытаюсь получить следующую запись:

<entry>
  <id>http://top.cs.vt.edu/libx2/vsony7@vt.edu/feed2/104</id>
  <title>New Title</title>
</entry>

Япарсинг xml с помощью xpath:

"/ atom: feed / atom: entry [atom: id = \" http://X/feed2/104\"]"

Но я получаю исключение, когда пытаюсь проанализировать Dom Element.Может кто-нибудь предложить простой подход для достижения этого в Java?

Пожалуйста, смотрите мой полный код:

public static parseXml() {
        String externalEntryIdUrl = "http://theta.cs.vt.edu/~rupen/thirtylibapps/137";
        String externalFeedUrl = StringUtils.substringBeforeLast(externalEntryIdUrl, "/");
        try {
            URL url = new URL(externalFeedUrl);
            InputStream externalXml = new BufferedInputStream(url.openStream());
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(externalXml);
            Element externalFeed = doc.getDocumentElement();
            String atomNameSpace = "xmlns:atom=\"http://www.w3.org/2005/Atom\"";
            String entryIdPath = String.format("//%s:entry[%s:id=%s]", atomNameSpace, atomNameSpace, externalEntryIdUrl);
            Element externalEntry = (Element) XPathSupport.evalNode(entryIdPath, externalFeed);
        } catch (Exception ex) {
            // Throw exception
        }
    }

static synchronized Node evalNode(String xpathExpr, Node node) {
    NodeList result = evalNodeSet(xpathExpr, node);
    if (result.getLength() > 1)
        throw new Error ("More than one node for:" + xpathExpr);
    else if (result.getLength() == 1)
        return result.item(0);
    else
        return null;
}

static synchronized NodeList evalNodeSet(String xpathExpr, Node node) {
        try {
                static XPath xpath = factory.newXPath();
                xpath.setNamespaceContext(context);

                static NamespaceContext context = new NamespaceContext() {
                    private Map<String, String> prefix2URI = new HashMap<String, String>();
                    {
                        prefix2URI.put("libx", "http://libx.org/xml/libx2");
                        prefix2URI.put("atom", "http://www.w3.org/2005/Atom");
                    }
                };

            XPathExpression expr = xpath.compile(xpathExpr);
            Object result = expr.evaluate(node, XPathConstants.NODESET);
            return (NodeList)result;
        } catch (XPathExpressionException xpee) {
            throw new Error ("An xpath expression exception: " + xpee);
        }
    }

SEVERE: >> java.lang.Error: Исключение выражения xpath: javax.xml.xpath.XPathExpressionException

Ответы [ 4 ]

0 голосов
/ 01 февраля 2012

Я понял, что не установил осведомленность о пространстве имен при извлечении xml из URL.

Итак,

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);

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

0 голосов
/ 30 января 2012

Вы можете использовать NamespaceContext и сделать что-то вроде следующего:

package forum9059851;

import java.io.FileInputStream;
import java.util.Iterator;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.*;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;

public class Demo {

    public static void main(String[] args) {
        try {
            XPathFactory xpf = XPathFactory.newInstance();
            XPath xp = xpf.newXPath();
            xp.setNamespaceContext(new MyNamespaceContext());
            XPathExpression xpe = xp.compile("ns:feed/ns:entry");
            FileInputStream xmlStream = new FileInputStream("src/forum9059851/input.xml");
            InputSource xmlInput = new InputSource(xmlStream);
            Element result = (Element) xpe.evaluate(xmlInput, XPathConstants.NODE);
            System.out.println(result);
        } catch (Exception ex) {
            // Throw exception
        }
    }

    private static class MyNamespaceContext implements NamespaceContext {

        public String getNamespaceURI(String prefix) {
            if("ns".equals(prefix)) {
                return "http://www.w3.org/2005/Atom";
            }
            return null;
        }

        public String getPrefix(String namespaceURI) {
            return null;
        }

        public Iterator getPrefixes(String namespaceURI) {
            return null;
        }

    }

}
0 голосов
/ 30 января 2012

Если вы не хотите заново изобретать колесо и хотите проанализировать данные подачи, я бы порекомендовал использовать уже имеющуюся библиотеку Rome .

0 голосов
/ 30 января 2012

Вы можете использовать SAX-парсер. Вот пример для разбора SAX http://www.mkyong.com/java/how-to-read-xml-file-in-java-sax-parser/

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