Что не так с этим кодом XML-синтаксического анализа Java? - PullRequest
1 голос
/ 04 января 2012

Я пытаюсь разобрать файл XML и могу вставить путь и получить значение поля.

Это выглядит следующим образом:

import java.io.IOException;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

public class XMLConfigManager {
    private Element config = null;

    public XMLConfigManager(String file) {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            Document domTree;
            DocumentBuilder db = dbf.newDocumentBuilder();
            domTree = db.parse(file);
            config = domTree.getDocumentElement();
        }
        catch (IllegalArgumentException iae) {
            iae.printStackTrace();
        }
        catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        }
        catch (SAXException se) {
            se.printStackTrace();
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    public String getStringValue(String path) {
        String[] pathArray = path.split("\\|");
        Element tempElement = config;
        NodeList tempNodeList = null;
        for (int i = 0; i < pathArray.length; i++) {
            if (i == 0) {
                if (tempElement.getNodeName().equals(pathArray[0])) {
                    System.out.println("First element is correct, do nothing here (just in next step)");
                }
                else {
                    return "**This node does not exist**";
                }
            }
            else {
                tempNodeList = tempElement.getChildNodes();
                tempElement = getChildElement(pathArray[i],tempNodeList);
            }
        }    
        return tempElement.getNodeValue();
    }
    private Element getChildElement(String identifier, NodeList nl) {
        String tempNodeName = null;
        for (int i = 0; i < nl.getLength(); i++) {
            tempNodeName = nl.item(i).getNodeName();
            if (tempNodeName.equals(identifier)) {
                Element returner = (Element)nl.item(i).getChildNodes();
                return returner;
            }
        }
        return null;
    }
}

XML выглядит следующим образом (для целей тестирования):

<?xml version="1.0" encoding="UTF-8"?>
<amc>
    <controller>
        <someOtherTest>bla</someOtherTest>
        <general>
            <spam>This is test return String</spam>
            <interval>1000</interval>
        </general>
    </controller>
    <agent>
        <name>test</name>
        <ifc>ifcTest</ifc>
    </agent>
</amc>

Теперь я могу назвать класс вот так

XMLConfigManager xmlcm = new XMLConfigManager("myConfig.xml");
System.out.println(xmlcm.getStringValue("amc|controller|general|spam"));

Здесь я ожидаю значение тега spam, так что это будет "This is test return String". Но я получаю null.

Я пытался исправить это уже несколько дней, и я просто не могу этого получить. Итерация работает, поэтому она попадает в тег spam, но затем, как я уже сказал, она возвращает null вместо текста.

Это ошибка или я просто не так делаю? Зачем? (

Большое спасибо за помощь!

С уважением, Фло

Ответы [ 4 ]

4 голосов
/ 04 января 2012

Вы звоните Node.getNodeValue() - что задокументировано, чтобы вернуть ноль, когда вы вызываете его для элемента.Вместо этого вы должны позвонить getTextContent() или использовать API более высокого уровня, конечно.

3 голосов
/ 04 января 2012

Как уже упоминалось до меня, вы, похоже, заново изобретаете концепцию XPath . Вы можете заменить свой код следующим:

javax.xml.xpath.XPath xpath = javax.xml.xpath.XPathFactory.newInstance().newXPath();
String expression = "/amc/controller/general/spam";
org.xml.sax.InputSource inputSource = new org.xml.sax.InputSource("myConfig.xml");
String result = xpath.evaluate(expression, inputSource);

См. Также: Проверка XML и оценка XPath в J2SE 5.0

EDIT:

Пример извлечения коллекции с помощью XPath:

NodeList result = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);
for (int i = 0; i < result.getLength(); i++) {
    System.out.println(result.item(i).getTextContent());
}

Интерфейс javax.xml.xpath.XPath задокументирован здесь , и есть еще несколько примеров в упомянутой статье .

Кроме того, существуют сторонние библиотеки для манипулирования XML, которые вы можете найти более удобными, такие как dom4j (предлагается duffymo ) или JDOM . Независимо от того, какую библиотеку вы используете, вы можете использовать довольно мощный язык XPath.

2 голосов
/ 04 января 2012

Поскольку вы используете getNodeValue() вместо getTextContent().

Выполнение этого вручную - случайность, ожидающая того, что произойдет; либо используйте встроенные решения XPath, либо стороннюю библиотеку, предложенную @duffymo. Это не та ситуация, когда переизобретение добавляет ценность, ИМО.

1 голос
/ 04 января 2012

Интересно, почему вы не используете библиотеку типа dom4j и встроенный XPath. Вы много работаете с API очень низкого уровня (WC3 DOM).

Перейдите к отладчику и посмотрите, какие дочерние узлы есть у этого <spam> узла. Вы должны быстро выяснить, почему это ноль. Это будет быстрее, чем спрашивать здесь.

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