2011-03-18 53 views
1

我一直试图在Android上构建一个应用程序,该应用程序从Labview RestFUL服务器获取数据。到目前为止,我已经能够完成一些合理的工作,但是当我需要从数组中解析数据时(名为Probability),我就陷入了困境。显示XML代码片段:在Java中使用相同的父代和子代标签解析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();    
} 
+2

我不知道这是你的问题,但你不应该使用==比较字符串。改用.equals。 ==只有在边是同一个对象时才是true,如果两个东西是等价对象(即具有相同的字符串值),.equals为真。 – 2011-03-18 20:04:43

+0

嗨,Mayra,它甚至没有达到字符串比较:调试时,可悲的事实仍然是,lName为空(我在IF语句中使用触发的断点) – Rasman 2011-03-18 20:22:21

+1

您可能更容易使用SAX而不是DOM解析此时间,并获得更好的启动性能。只要确保不要使用'=='来比较那里的字符串,就像@Mayra指出的那样。 – CommonsWare 2011-03-18 20:46:48

回答

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代表标签的'level'。

使用STAX,您可以对事件进行流式处理,只需要处理您感兴趣的事件。如果您对“开始元素事件”感兴趣,则可以获取它们,并保持光标状态类似于你如何使用SAX解析器。

+0

Android上没有stax :(我会看看我是否可以获得SAX – Rasman 2011-03-19 04:52:35

0

正如nicholas.hauschild所提到的那样,您可以使用SAX解析器来执行此操作。但我不认为你需要水平变量来区分这两个标签。

每当有数据需要读取时,它将调用characters()方法,并且可以读取其中的值。由于父代<Value>标签没有自己的任何数据(除了嵌套标签),它不会调用characters()方法。

+0

我想象你仍然需要保持某种状态,就像在Rasman的例子中,你会碰到顶级元素中的多个字符部分,并且characters()方法没有提及它的直接父对象(或任何父对象)。 – 2011-03-18 22:10:40

+0

对不起 - 我不明白为什么你需要知道关卡的级别,只有在有数据时才会调用characters()方法当有数据要被读取时,你可以通过调用你的方法来读取它,我可能会在这里丢失一些东西,而OP必须已经找到了答案,所以我们不妨放手! – user183037 2011-03-31 07:23:39