2012-02-08 7 views
0

XML 데이터 문자열을 반환하는 .NET 웹 서비스를 사용하는 앱이 있습니다. 이 XML을 읽고 로컬 SQLite DB에 삽입하려고하는데 문제가 있습니다. 다음은 XML의 샘플입니다 : 내가 디버거를 통해 실행Android - XML ​​문제 읽기

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"잘을 가져옵니다

<?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을 사용하여, 나는 지금과 같은 결과를 분석하려고 해요 하지만 바로 다음 노드 인 "IssueSummary"를 픽업하여 한 번에 데이터를 삽입 할 수있는 방법은 무엇입니까? 어딘가에 또 다른 루프가 필요한 것처럼 보이지만, 확실하지는 않습니다.

+0

Android에만 해당되는가요? 즉, IDE에서 일반적인 오래된 자바처럼 코드를 실행하는 데 동일한 오류가 발생합니까? 언뜻보기에는 'IssueID'를 가져 오는 것과 같은 방식으로 'IssueSummary'에 액세스 할 수없는 이유가없는 것처럼 보입니다. –

+0

저는 Android 개발에 익숙하지 않지만 Eclipse로이 앱을 개발하고 있습니다. 디버깅 할 때 Android 앱으로 사용됩니다. 자바 애플 리케이션으로 실행하는 방법을 잘 모르겠습니다. – Robert

+0

Java/Android와 상관없이 DOM을 파싱합니다. – kosa

답변

0

마침내 제 동료와 도움을 받아이 문제를 해결했습니다.DataSet.GetXml()에서 XmlDocument.InnerXml로 문자열을 반환 한 WebService를 변경 한 점에 유의해야합니다. 이것은 노드 사이의 공간을 제거하고 거기에서 앞으로 나아갈 수있었습니다. 여기에 우리가 사용하는 최종 코드입니다 :

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 방법 : Programmer XR을하고 그것을 수정 : 확실히이에 대한 크레딧을 복용하지

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 ""; 
} 

, 난 여기가 발견 내 필요.

다른 사람들에게 도움이되기를 바랍니다.

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> "); 

. 적어도 저로서는 괜찮습니다. 그것은 밖으로 인쇄합니다 :

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

예, 시도했습니다. 다른 Node 변수를 만들고 issue.setIssueNumber 문법 바로 다음에 설정 한 다음 새 노드를 사용하여 IssueSummary를 가져 왔지만 선택하지 않았습니다. – Robert

+0

죄송합니다. 회의 중입니다 ... 코드를 시도했지만 동일한 결과를 얻지 못했습니다. IssueID가 인쇄되었지만 IssueSummary에는 아무것도 표시되지 않습니다. 그래서 나는 다시 xml을보고 잘못된 XML을 게시 한 것처럼 보입니다. 위의 게시물을 새 게시물로 편집했습니다. 사실 전혀 다르지 않습니다. 제가 찾고있는 두 필드가 여전히 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하지 않아도됩니다 하나 개 이상의 값 세트 이마 난다.

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

당신은 아마 너무 for 외부 최종 if를 이동해야하므로 한 번 이상 실행되지 것 :

그냥 두 줄을 한 번만 issue를 만들 교환합니다.

실제로 두 번째 if에 요약을 설정해야합니다. '발행 번호'를 두 번 설정하고 있습니다.

+0

시도했지만 너무 운이 ... – Robert