2012-02-08 12 views
0

XMLの文字列を返す.NET Webサービスを利用するアプリケーションがあります。私はこのXMLを読んでローカルのSQLite DBに挿入しようとしていますが、何か問題があります。ここでは、XMLのサンプルです:Android - XMLの問題を読む

DOMを使用して
<?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> 

、私はそうのような結果を解析しようとしている:

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」にアクセスできない理由はないようです。 –

+0

私はAndroidの開発にはかなり新しいですが、私はこのアプリをEclipseで開発しています。デバッグするときは、Android Appと同じです。 Javaアプリケーションとして実行する方法はわかりません。 – Robert

+0

Java/Androidに関係なくDOMを解析します。 – kosa

答えて

0

最後に、私の同僚と助手の助けを借りてこれに対する解決策を見つけました。DataSet.GetXml()の文字列を返すWebServiceを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(); 
    } 


} 

と私はこのようにそれを呼び出す:単純なJavaクラスから

GetLatestData("<OpenIssues> " + 
"<Table> " + 
    "<IssueID>15351</IssueID>" + 
    "<IssueSummary>Computer keeps crashing. This continues to be a problem</IssueSummary> " + 
    "<Notes />" + 
"</Table></OpenIssues> "); 

。少なくとも私にとってはうまくいきます。

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

はい、私はそれを試みました。別のNode変数を作成し、issue.setIssueNumber文の直後に設定してから、その新しいノードを使用してIssueSummaryを取得しましたが、それを受け取っていません。 – Robert

+0

申し訳ありませんが、会議中でした。私はあなたにコードを試みましたが、同じ結果を得ていませんでした。 IssueIDは印刷されますが、IssueSummaryには何も表示されません。だから、私は再びxmlを見て、間違ったxmlを投稿したように見えます。私は上の私のポストを新しいもので編集しました。実際には、私が探している2つのフィールドはまだ1&2なので、それはまだ動作するはずですよね?私が考えることができるのは、書式設定がオフの場合のみです。 – Robert

+1

あなたは正しいです。私がXMLコードをそのまま使用すると、空の要約も得られます(ノードの次の兄弟は ""です)。しかし、式tempNode.getNextSibling()。getNextSibling()。getTextContent()を使用すると、正しい結果が得られます。私はあなたがノードが互いに隣り合っていることを保証できるかどうか尋ねたのです。 – DigCamara

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を作成するために2行を入れ替える:

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

それが複数回実行いないので、あなたはおそらく、あまりにもfor外で最終ifを移動する必要があります。

2番目のifのサマリーは実際に設定する必要があります。 'issue number'を2回設定しています。

+0

これも試しましたが、まだ運がない... – Robert

関連する問題