使用相同的父标记和子标记在Java中解析XML

时间:2011-03-18 19:57:56

标签: java xml xml-parsing

我一直在尝试在Android上构建一个从Labview RestFUL服务器获取数据的应用程序。到目前为止,我已经能够完成相当多的工作,但是当我需要来自数组的解析数据(名为Probability)时,我就陷入了困境。显示了一段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解析技术而且没有用(如果我在父节点中搜索“Values”,它会返回相同的父节点)。所以我开始使用更多的创造性技术而没有好的结果。例如下面的代码,我只调用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();            
}

2 个答案:

答案 0 :(得分: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解析器。

答案 1 :(得分:0)

正如nicholas.hauschild所提到的,你可以使用SAX Parser来做到这一点。但我认为你不需要水平变量来区分这两个标签。

每当有数据要读取时,它都会调用characters()方法,你可以读取其中的值。由于父<Value>标记没有自己的任何数据(除了嵌套标记),因此它不会调用characters()方法。