2012-02-08 61 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