2012-02-08 67 views
0

我有一個應用程序,它使用.NET Web服務,它返回一個XML數據字符串。我試圖讀取這個XML並將其插入本地SQLite數據庫,但我遇到了一些麻煩。下面是XML的一個樣本:Android - 讀取XML問題

<?xml version="1.0" encoding="utf-8" ?> 
<string xmlns="RemoteWebService"><OpenIssues> <Table> <IssueID>15351</IssueID> <IssueSummary>Computer keeps crashing. This continues to be a problem</IssueSummary> <LocationName>West Side</LocationName> <Status>WIP</Status> <CustomerID>89755</CustomerID> <CustomerName>West Side Computers</CustomerName> <CustomerShortName>WSC</CustomerShortName> <Notes /> <STATUS1>Work In Progress</STATUS1> <SubmittedBy>WSC - Tom Johns</SubmittedBy> <EQ_Replaced>true</EQ_Replaced></Table> </OpenIssues></string> 

使用DOM,我試圖解析結果像這樣:

private void GetLatestData(String response) throws ParserConfigurationException, SAXException, IOException{ 

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    DocumentBuilder db = dbf.newDocumentBuilder(); 
    Document doc = db.parse(new InputSource(new StringReader(response))); 

    //Normalize the document. 
    doc.getDocumentElement().normalize(); 

    //Get Root Node. 
    NodeList nodeList = doc.getElementsByTagName("Table"); 
    Node node = nodeList.item(0); 

    //Get Child Nodes. 
    for(int i = 0; i < node.getChildNodes().getLength(); i++){ 
     IssueInfo issue = new IssueInfo(); 
     Node tempNode = node.getChildNodes().item(i); 

     if(tempNode.getNodeName().equalsIgnoreCase("IssueID")){ 
      issue.setIssueNumber(Long.parseLong(tempNode.getTextContent())); 
     } 

     if(tempNode.getNodeName().equalsIgnoreCase("IssueSummary")){ 
      issue.setIssueNumber(Long.parseLong(tempNode.getTextContent())); 
     }    

     if(issue.getIssueNumber() > 0 && issue.getIssueSummary() != null){ 
      creator = new IssueInfoCreator(this, DBVersion); 
      creator.open(); 
      creator.InsertIssue(issue.getIssueNumber(), DateFormat.getDateInstance().format(new Date()), issue.getIssueSummary()); 
      creator.close(); 
     } 
    } 
} 

當我運行它通過調試器,它就會「IssueID」就好了但是我怎麼才能在它之後找到下一個節點「IssueSummary」,這樣我就可以一次插入數據?似乎我需要另一個循環,只是不太確定。

+0

是否特定於Android?也就是說,在IDE中運行代碼時是否會出現與原始Java相同的錯誤?乍看之下,您似乎沒有理由不能像抓取'IssueID'一樣訪問'IssueSummary'。 – 2012-02-08 18:37:49

+0

我對Android開發很新,但是我正在用Eclipse開發這個應用程序,當我調試它時,它就像一個Android應用程序。不知道如何將它作爲Java應用程序運行。 – Robert 2012-02-08 18:41:25

+0

這是DOM解析不考慮Java/Android。 – kosa 2012-02-08 18:50:37

回答

0

終於在我的同事的幫助下找到了解決辦法,還有一些挖掘方法。應該注意的是,我們將返回一個字符串的WebService從DataSet.GetXml()更改爲XmlDocument.InnerXml。這刪除了節點之間的空間,然後我們能夠從那裏向前移動。下面是我們使用的最終代碼:

public void GetLatestData(SoapPrimitive xml)throws ParserConfigurationException, SAXException, IOException{ 
    //get the factory 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 

    //Using factory get an instance of document builder 
    DocumentBuilder db = dbf.newDocumentBuilder(); 
    Document doc; 

    //parse using builder to get DOM representation of the XML file 
    InputSource is = new InputSource(new StringReader(xml.toString())); 
    doc = db.parse(is); 

    //Clear out Issues table first. 
    creator = new IssueInfoCreator(this, DBVersion); 
    creator.open(); 
    creator.ClearIssueTable(); 
    creator.close(); 

    NodeList nodes = doc.getElementsByTagName("Table"); 

    for(int i = 0; i < nodes.getLength(); i++) { 
     IssueInfo issue = new IssueInfo(); 

     Element e = (Element)nodes.item(i); 

     issue.setIssueNumber(Long.parseLong(XMLfunctions.getValue(e, "IssueID"))); 
     issue.setIssueSummary(XMLfunctions.getValue(e, "IssueSummary")); 
     issue.setDateReceived(DateFormat.format("MM/dd/yyyy hh:mm:ss", System.currentTimeMillis()).toString()); 

     if(issue.getIssueNumber() > 0 && issue.getIssueSummary() != null){ 
      creator = new IssueInfoCreator(this, DBVersion); 
      creator.open(); 
      creator.InsertIssue(issue.getIssueNumber(), issue.getDateReceived(), issue.getIssueSummary()); 
      creator.close(); 
     } 
    } 
} 

這裏是XMLfuntions類的getValue方法:

public static String getValue(Element item, String str) {  
    NodeList n = item.getElementsByTagName(str);   
    return XMLfunctions.getElementValue(n.item(0)); 
} 

public final static String getElementValue(Node elem) { 
    Node kid; 
    if(elem != null){ 
     if (elem.hasChildNodes()){ 
      for(kid = elem.getFirstChild(); kid != null; kid = kid.getNextSibling()){ 
       if(kid.getNodeType() == Node.TEXT_NODE ){ 
        return kid.getNodeValue(); 
       } 
      } 
     } 
    } 
    return ""; 
} 

絕對不是爭名奪利對於這一點,我在這裏找到: Programmer XR並修改我的需求。

希望這會幫助別人!

1

看起來像一個簡單的DOM遍歷問題。

如果你能保證下一個節點是總結,你可以嘗試使用getNextSibling()方法節點

我修改你的代碼,所以我可以把它不使用你的類。這是我使用的代碼:

private static void GetLatestData(String response) { 
    try{ 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
       /* the following 2 lines help you eliminate whitespace 
        from your xml DOM tree */ 
     dbf.setValidating(true); 
     dbf.setIgnoringElementContentWhitespace(true); 

     DocumentBuilder db = dbf.newDocumentBuilder(); 
     DocumentBuilder db = dbf.newDocumentBuilder(); 
     Document doc = db.parse(new InputSource(new StringReader(response))); 

     //Normalize the document. 
     doc.getDocumentElement().normalize(); 

     //Get Root Node. 
     NodeList nodeList = doc.getElementsByTagName("Table"); 
     Node node = nodeList.item(0); 
     long issueNumber; 
     String summary; 

     //Get Child Nodes. 
     for(int i = 0; i < node.getChildNodes().getLength(); i++){ 

      Node tempNode = node.getChildNodes().item(i); 


      if(tempNode.getNodeName().equalsIgnoreCase("IssueID")){ 
       issueNumber = (Long.parseLong(tempNode.getTextContent())); 
       Node summaryNode = tempNode.getNextSibling(); 

       summary = summaryNode.getTextContent(); 
       System.out.println(String.format("Issue # %d, Summary: %s" , issueNumber,summary)); 
      } 
     } 


    }catch(Exception exception){ 
     exception.printStackTrace(); 
    } 


} 

,我這樣稱呼它:

GetLatestData("<OpenIssues> " + 
"<Table> " + 
    "<IssueID>15351</IssueID>" + 
    "<IssueSummary>Computer keeps crashing. This continues to be a problem</IssueSummary> " + 
    "<Notes />" + 
"</Table></OpenIssues> "); 
從一個簡單的Java類

。至少,它對我來說很好。它打印出來:

Issue # 15351, Summary: Computer keeps crashing. This continues to be a problem 
+0

是的,我試過了。我創建了另一個Node變量,並將其設置爲緊跟在issue.setIssueNumber statment之後,然後使用該新節點獲取IssueSummary,但它沒有選擇它。 – Robert 2012-02-08 18:48:17

+0

對不起,正在開會......我試過你的代碼,但沒有得到相同的結果。 IssueID已打印,但沒有顯示IssueSummary。所以我再次看看我的XML,看起來像我發佈了錯誤的XML。我用新的編輯過我的帖子。事實並非如此,事實上,我所尋找的兩個領域仍然是1&2,所以它仍然可以工作,對吧?我能想到的唯一情況是格式化是否關閉? – Robert 2012-02-08 20:21:58

+1

你完全正確。如果我按照原樣獲取xml代碼,我也會得到一個空的摘要(該節點的下一個兄弟是「」)。如果我使用表達式tempNode.getNextSibling()。getNextSibling()。getTextContent(),但是,我得到正確的結果。我想這就是爲什麼我問你是否可以保證節點坐在一起。 – DigCamara 2012-02-08 20:35:56

1

如果我正確理解你的問題,這是你可能需要做的。

Node node = nodeList.item(0); 

返回

<Table> 
     <IssueID>15351</IssueID> 
     <IssueSummary>Computer keeps crashing. This continues to be a problem</IssueSummary> 
     <Notes /> 
    </Table> 

node.getChildNodes().getLength(); 

返回3

IssueInfo issue = new IssueInfo(); 

//仔細檢查每個孩子,並找出節點名稱和填充它。

for(int i = 0; i < node.getChildNodes().getLength(); i++){ 

     Node tempNode = node.getChildNodes().item(i); 

     if(tempNode.getNodeName().equalsIgnoreCase("IssueID")){ 
      issue.setIssueNumber(Long.parseLong(tempNode.getTextContent())); 
     } 

     if(tempNode.getNodeName().equalsIgnoreCase("IssueSummary")){ 
      issue.setIssueNumber(Long.parseLong(tempNode.getTextContent())); 
     }    


    } 

如果邏輯超出循環,則移動。

if(issue.getIssueNumber() > 0 && issue.getIssueSummary() != null){ 
      creator = new IssueInfoCreator(this, DBVersion); 
      creator.open(); 
      creator.InsertIssue(issue.getIssueNumber(), DateFormat.getDateInstance().format(new Date()), issue.getIssueSummary()); 
      creator.close(); 
     } 
0

*嫌額頭*

issue將永遠不會有一個以上的值設定,因爲它是重新創建的每個子節點。

只是交換兩行創建issue只有一次:

IssueInfo issue = new IssueInfo(); 
for(int i = 0; i < node.getChildNodes().getLength(); i++){ 
    ... 

你或許應該移動for過外面的最終if,所以它不是執行一次以上。

而且您需要在第二個if中實際設置摘要。你正在設置'問題編號'兩次。

+0

也試過這個,但仍然沒有運氣... – Robert 2012-02-08 20:30:57