разбор XML в Java с идентичными родительскими и дочерними тегами

Я пытался создать приложение на Android, которое получает данные с сервера Labview RestFUL. До сих пор мне удавалось добиться довольно многого, но я застрял, когда мне нужно проанализировать данные из массива (с именем Вероятность). Показан фрагмент кода XML:

<Response>
    <Terminal>
        <Name>Push</Name>
        <Value>77.678193</Value>
    </Terminal>
    <Terminal>
        <Name>Pull</Name>
        <Value>153.621879</Value>
    </Terminal>
(snip)
    <Terminal>
        <Name>Probability</Name>
        <Value>
            <DimSize>480</DimSize>
            <Name>effect</Name>
            <Value>0.000000</Value>
            <Name>effect</Name>
            <Value>0.000000</Value>
            <Name>effect</Name>
(snip)
        </Value>
    </Terminal>
</Response>

Как видите, LabView использует вложенный тег значения.

Я использовал стандартные методы синтаксического анализа XML, и это не сработало (если я ищу «Значения» в родительском узле, он возвращает тот же родительский узел). Поэтому я начинаю использовать более творческие методы без хороших результатов. Например, в приведенном ниже коде я вызываю if ( lName == "Value") только для того, чтобы обнаружить, что для lName установлено значение Null.

Любой совет там?

InputStream firstData = null;
URL url = null;
try {
    url = new URL(urlString);
} catch (MalformedURLException e2) {
    // TODO Auto-generated catch block
    e2.printStackTrace();
} 
int response = -1;


try {
    URLConnection conn = url.openConnection();
    Document doc = null;
    DocumentBuilderFactory dbf = 
        DocumentBuilderFactory.newInstance();
    DocumentBuilder db;

    HttpURLConnection httpConn = (HttpURLConnection) conn;
    httpConn.setAllowUserInteraction(false);
    httpConn.setInstanceFollowRedirects(true);
    httpConn.setRequestMethod("GET");
    httpConn.connect(); 

    response = httpConn.getResponseCode();                 
    if (response == HttpURLConnection.HTTP_OK) {
        firstData = httpConn.getInputStream();                                 
    }                     

    try {
        db = dbf.newDocumentBuilder();
        doc = db.parse(firstData);
    } catch (ParserConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SAXException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }        

    doc.getDocumentElement().normalize(); 

    NodeList terminalNodes = doc.getElementsByTagName("Terminal"); 

    for (int i = 0; i < 4; i++) { 
        Node singleTerminalNode = terminalNodes.item(i); 
        if (singleTerminalNode.getNodeType() == Node.ELEMENT_NODE) 
        {            
            Element firstLevel = (Element) singleTerminalNode;

            NodeList value1Nodes = (firstLevel).getElementsByTagName("Value");

            Element value1Element = (Element) value1Nodes.item(0);

            if (i<FIRST_SET){
                NodeList digit1Nodes = ((Node) value1Element).getChildNodes();
                hinde[i] = Double.parseDouble(((Node) digit1Nodes.item(0)).getNodeValue());
            }
            else 
                {
                NodeList value1Children = ((Node) value1Element).getChildNodes();

                int henry = value1Children.getLength();
                int counter = 0;
                String lName;



                for (int j = 0; i < henry; j++){                

                    Element digit2Element = (Element) value1Children.item(j);
                    lName = digit2Element.getLocalName();
                    if ( lName == "Value")
                    {
                    NodeList digit2Nodes = ((Node) digit2Element).getChildNodes();
                    sweep[counter] = Double.parseDouble(((Node) digit2Nodes.item(0)).getNodeValue());
                    counter ++;
                    }
                }
                }
        } 
    }   
} catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();            
}

person Rasman    schedule 18.03.2011    source источник
comment
Я не знаю, является ли это вашей проблемой, но вы не должны использовать == для сравнения строк. Вместо этого используйте .equals. == верно, только если стороны являются одним и тем же объектом, .equals верно, если две вещи являются эквивалентными объектами (т.е. имеют одинаковое строковое значение).   -  person Cheryl Simon    schedule 18.03.2011
comment
Привет, Майра, это даже не доходит до сравнения строк: при отладке остается печальная правда, что lName имеет значение null (я использовал срабатывание точки останова в операторе IF)   -  person Rasman    schedule 18.03.2011
comment
Вам может быть проще разобрать это, используя SAX вместо DOM, и получить лучшую производительность для загрузки. Просто не используйте == для сравнения строк, как указывает @Mayra.   -  person CommonsWare    schedule 18.03.2011


Ответы (2)


Я предполагаю, что это можно сделать с помощью синтаксического анализатора DOM, но это может быть проще реализовать с помощью синтаксического анализатора SAX или STAX (он также будет иметь меньший отпечаток памяти!).

http://download.oracle.com/javase/1.4.2/docs/api/javax/xml/parsers/SAXParser.html

http://download.oracle.com/javaee/5/tutorial/doc/bnbem.html

С помощью SAX вы создаете обработчик, который будет получать события, когда синтаксический анализатор достигает определенных точек в документе. С тегами, которые можно встроить, вы можете использовать свой обработчик для сохранения состояния курсора. Например, когда вы видите первый тег, у вас может быть int, представляющий «уровень» тега.

С помощью STAX вы выполняете потоковую передачу событий, и вам нужно иметь дело только с теми событиями, которые вас интересуют. Если вас интересуют «события начального элемента», вы можете получить их и сохранить состояние курсора, аналогичное тому, как вы это сделали бы с парсер SAX.

person nicholas.hauschild    schedule 18.03.2011
comment
Нет stax на Android :( Я посмотрю, смогу ли я запустить SAX - person Rasman; 19.03.2011

Как упоминал nicholas.hauschild, для этого вы можете использовать SAX Parser. Но я не думаю, что вам нужна переменная уровня, чтобы различать два тега.

Всякий раз, когда есть данные для чтения, он вызывает метод character(), и вы можете прочитать значения из него. Поскольку родительский тег <Value> не имеет собственных данных (кроме вложенных тегов), он не вызывает метод character().

person user183037    schedule 18.03.2011
comment
Я предполагаю, что вам все равно нужно было бы сохранять какое-то состояние, как в примере Расмана, вы бы нажимали несколько секций символов внутри элемента ‹value› верхнего уровня, а метод character() не упоминал, что его прямой родитель (или любой родитель ) является. - person nicholas.hauschild; 19.03.2011
comment
Извините - я не понимаю, зачем вам нужно знать уровень, метод character() вызывается только в том случае, если есть данные для чтения, а когда есть данные для чтения, вы просто идете вперед и читаете их, вызывая ваш метод. Возможно, я что-то упускаю здесь, и ОП, должно быть, уже нашел ответ, так что мы могли бы его оставить! :) - person user183037; 31.03.2011