2012-08-06 5 views
2

RSS 피드에서 데이터를 읽는 목표로 연습 응용 프로그램을 만들고 있습니다.자바 읽기 XML - '<'특수 문자에서 멈춤

내 응용 프로그램에 특수 문자 문제가 발생하는 것을 제외하고는 지금까지 잘 진행되었습니다. 노드 내의 첫 번째 특수 문자를 읽고 다음 노드로 이동합니다.

도움이 될만한 큰 코드 블록은 유감스럽게 생각합니다.

RSS 피드 - www.usu.co.nz/usu-news/rss.xml

<title>Unitec hosts American film students</title> 
<link>http://www.usu.co.nz/node/4640</link> 
<description>&lt;p&gt;If you’ve been hearing American accents around the Mt Albert campus over the past week.</description> 

디스플레이 코드

String xml = XMLFunctions.getXML(); 
Document doc = XMLFunctions.XMLfromString(xml); 

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

for (int i = 0; i < nodes.getLength(); i++) 
{       
    Element e = (Element)nodes.item(i); 
    Log.v("XMLTest", XMLFunctions.getValue(e, "title")); 
    Log.v("XMLTest", XMLFunctions.getValue(e, "link")); 
    Log.v("XMLTest", XMLFunctions.getValue(e, "description")); 
    Log.v("XMLTest", XMLFunctions.getValue(e, "pubDate")); 
    Log.v("XMLTest", XMLFunctions.getValue(e, "dc:creator")); 
} 

리더 코드

public class XMLFunctions 
{ 

public final static Document XMLfromString(String xml) 
{ 

    Document doc = null; 

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    try { 

     DocumentBuilder db = dbf.newDocumentBuilder(); 

     InputSource is = new InputSource(); 
     is.setCharacterStream(new StringReader(xml)); 
     doc = db.parse(is); 

    } catch (ParserConfigurationException e) { 
     System.out.println("XML parse error: " + e.getMessage()); 
     return null; 
    } catch (SAXException e) { 
     System.out.println("Wrong XML file structure: " + e.getMessage()); 
     return null; 
    } catch (IOException e) { 
     System.out.println("I/O exeption: " + e.getMessage()); 
     return null; 
    } 

    return doc; 

} 

/** Returns element value 
    * @param elem element (it is XML tag) 
    * @return Element value otherwise empty String 
    */ 
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 ""; 
} 

public static String getXML(){ 
     String line = null; 

     try { 

      DefaultHttpClient httpClient = new DefaultHttpClient(); 
      HttpPost httpPost = new HttpPost("http://www.usu.co.nz/usu-news/rss.xml"); 

      HttpResponse httpResponse = httpClient.execute(httpPost); 
      HttpEntity httpEntity = httpResponse.getEntity(); 
      line = EntityUtils.toString(httpEntity); 

     } catch (UnsupportedEncodingException e) { 
      line = "<results status=\"error\"><msg>Can't connect to server</msg></results>"; 
     } catch (MalformedURLException e) { 
      line = "<results status=\"error\"><msg>Can't connect to server</msg></results>"; 
     } catch (IOException e) { 
      line = "<results status=\"error\"><msg>Can't connect to server</msg></results>"; 
     } 

     return line; 

} 

public static int numResults(Document doc){  
    Node results = doc.getDocumentElement(); 
    int res = -1; 

    try{ 
     res = Integer.valueOf(results.getAttributes().getNamedItem("count").getNodeValue()); 
    }catch(Exception e){ 
     res = -1; 
    } 

    return res; 
} 

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

출력

Unitec hosts American film students 
http://www.usu.co.nz/node/4640 
< 
Wed, 01 Aug 2012 05:43:22 +0000 
Phillipa 
+1

답변이 없으므로 상위 XML API를 사용하여 이러한 항목을 읽으셨습니까? Apache [XMLBeans] (http://xmlbeans.apache.org/)와 같은 라이브러리를 사용하면 XML을 편리한 Java 객체로 쉽게 파싱 할 수 있습니다. "재미있는"캐릭터 및 기타 이상한 점에 대해서도 잘 테스트됩니다. –

답변

2

함수는 지정된 요소 아래의 첫 번째 텍스트 노드를 반환한다. 단일 태그 내의 텍스트 묶음은 여러 텍스트 노드로 나눌 수 있으며 특수 문자가있는 경우에 발생합니다.

모든 텍스트 노드를 반환 값의 문자열에 추가해야합니다. 약이 같은

뭔가 작동 할 수 있습니다 :

public final static String getElementValue(Node elem) { 
    if ((elem == null) || (!(elem.hasChildNodes()))) 
     return ""; 

    Node kid; 
    StringBuilder builder = new StringBuilder(); 
    for(kid = elem.getFirstChild(); kid != null; kid = kid.getNextSibling()) 
    { 
     if(kid.getNodeType() == Node.TEXT_NODE ) 
     { 
      builder.append(kid.getNodeValue()); 
     } 
    } 
    return builder.toString(); 
} 
+0

StringBuilder를 사용할 수있는 경우 StringBuffer를 사용하지 마십시오. –

+0

맞아. StringBuilder를 사용하도록 개정했습니다. –

0

<?xml version="1.0" encoding="UTF-8"?>이 누락 된 것 같습니다. 또한 루트 요소가 없습니다.

+0

여기서 XML 조각을 볼 수 있다고 가정합니다. "Phillipa"라는 컨트 리뷰 터를 포함하고 있지 않다는 것을 유의하십시오. 그러나 이것은 출력에서 ​​참조됩니다. –

+0

죄송합니다. 분명히해야합니다. 난 단지 XML의 작은 부분을 보여 주려고 했으므로 문제가있는 특수 문자를 볼 수있었습니다. – Aelexe

0

XML 문자열이 DefaultHttpClient에 의해 변환되지 않았습니까? 내가 코드를 시도하고 DefaultHttpClient하여 얻는 대신 직접 XML 문자열을 공급하는 방법 XMLFunctions.getXML()를 변경, 출력은 예상대로

Unitec hosts American film students 
http://www.usu.co.nz/node/4640 
<p>If you’ve been hearing American accents around the Mt Albert campus over the past week. 

같다.

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

3

귀하의 코드는 요소에서 자식 텍스트 노드를 추출합니다. DOM 스펙은 여러 개의 인접한 텍스트 노드를 허용하므로 여기서 파서는 <, p, > 및 나머지 텍스트를 (적어도) 4 개의 개별 텍스트 노드로 나타냅니다. 노드를 하나의 문자열로 연결하거나 포함 된 요소 노드 (인접한 텍스트 노드를 하나로 병합하도록 DOM 트리를 수정 함)에서 normalize()을 호출해야합니다.

당신을 도울 수있는 다양한 라이브러리가 있습니다. 예를 들어 응용 프로그램이 Spring 프레임 워크를 사용하는 경우 org.springframework.util.xml.DomUtils은 요소에서 전체 텍스트 값을 추출하는 getTextValue 정적 메서드를가집니다.

+0

+1 : 게시 한 것보다이 문제에 대한 해결책이 될 수 있습니다. –

1

화제가 아니지만 이미 존재하는 RSS 프레임 워크 중 하나 인 ROME을 확인해보십시오. 휠을 다시 발명하는 것보다 낫습니다.