2010-01-12 78 views
2

再次提出一个问题。这一次我正在解析从服务器接收到的XML消息。 有人认为是聪明的,并决定将HTML页面放在XML消息中。现在我遇到了一些问题,因为我想从该XML消息中提取该HTML页面作为字符串。Android:解析XML DOM解析器。将子节点转换为字符串

好吧,这是我解析XML消息:

<AmigoRequest> <From></From> <To></To> <MessageType>showMessage</MessageType> <Param0>general message</Param0> <Param1><html><head>test</head><body>Testhtml</body></html></Param1> </AmigoRequest>

你看,在参数1中指定的HTML页面。我尝试通过以下方式提取消息:

 
public String getParam1(Document d) { 
     if (d.getDocumentElement().getTagName().equals("AmigoRequest")) { 
      NodeList results = d.getElementsByTagName("Param1"); 
      // Messagetype depends on what message we are reading.   
      if (results.getLength() > 0 && results != null) {     
       return results.item(0).getFirstChild().getNodeValue(); 
      } 
     } 
     return ""; 
    } 

其中,d是文档格式的XML消息。 它总是返回一个空值,因为getNodeValue()返回null。 当我尝试results.item(0).getFirstChild()。hasChildNodes()时,它将返回true,因为他看到消息中有一个标记。

如何从Param0中提取html消息<html><head>test</head><body>Testhtml</body></html>中的字符串?

我正在使用Android sdk 1.5(几乎是java)和一个DOM解析器。

感谢您的时间和答复。

ANTEK

+0

是XPath的一个选择吗?如果是这样,我可能会帮助你,而我从来没有使用过,这就是我问的原因。 – ChadNC 2010-01-12 17:35:17

+0

XPath不受支持,但我设法通过使用DOM4J和Jaxen来为Android找到解决方法。 – 2010-01-13 09:20:38

回答

1

你可以采取参数1的内容,就像这样:

public String getParam1(Document d) { 
     if (d.getDocumentElement().getTagName().equals("AmigoRequest")) { 
      NodeList results = d.getElementsByTagName("Param1"); 
      // Messagetype depends on what message we are reading.   
      if (results.getLength() > 0 && results != null) {     

       // String extractHTMLTags(String s) is a function that you have 
       // to implement in a way that will extract all the HTML tags inside a string. 
       return extractHTMLTags(results.item(0).getTextContent()); 
      } 
     } 
     return ""; 
    } 

所有你需要做的就是实现一个功能:

String extractHTMLTags(String s) 

,将删除所有HTML标记字符串中的事件。 对于您可以看看这篇文章:Remove HTML tags from a String

+0

太糟糕Android不支持getTextContent功能。 Android正在使用旧的dom解析器。但我知道现在看哪里。仍然没有找到该主题的解决方案,但我编辑了我的主题标题。 – 2010-01-12 17:36:16

+1

如果'getTextContent'在平台上可用,只需调用它就足够了,而不用在其周围包含'extractHTMLTags'调用。 getTextContent从所返回的字符串中去掉任何XML标记(更准确地说,它通过连接嵌套元素内的所有文本字符串来获得它的值,同时留下元素标记)。当然,这确实假定HTML内容是格式良好的XML。但是,如果不是这样,那么在XML解析中你可能甚至不会达到这样的程度。 – 2010-01-12 17:45:52

+0

哦,我从来没有使用过android,我不知道它的DOM解析器!我认为这是使用最新版本。对于那个很抱歉! – Alex 2010-01-12 17:48:36

0

编辑:我刚才看到上面关于getTextContent()不支持Android平台上的评论。如果对不同平台上的某个人有用,我会留下这个答案。

如果你的DOM API支持的话,你可以打电话getTextContent(),如下:

public String getParam1(Document d) { 
     if (d.getDocumentElement().getTagName().equals("AmigoRequest")) { 
      NodeList results = d.getElementsByTagName("Param1"); 
      // Messagetype depends on what message we are reading.   
      if (results != null) {     
       return results.getTextContent(); 
      } 
     } 
     return ""; 
    } 

然而,getTextContent()是DOM Level 3的API调用;并非所有的解析器都保证支持它。 Xerces-J does

顺便说一句,在你原来的例子中,你的支票null是在错误的地方;它应该是:

 if (results != null && results.getLength() > 0) {     

否则,你会得到一个NPE如果results确实回来为null

0

由于getTextContent()不适用于您,另一个选择是写它 - 这并不难。事实上,如果你仅仅是为了自己的用途而编写这个代码 - 或者你的雇主没有对开放源代码有严格的规定 - 你可以看看Apache's implementation作为一个起点;第610-646行似乎包含你所需要的大部分内容。 (请尊重Apache的版权和许可)

否则,该方法的一些粗略的伪代码将是:

String getTextContent(Node node) { 
    if (node has no children) 
     return ""; 

    if (node has 1 child) 
     return getTextContent(node.getFirstChild()); 

    return getTextContent(new StringBuffer()).toString(); 
} 

StringBuffer getTextContent(Node node, StringBuffer sb) { 
    for each child of node { 
     if (child is a text node) sb.append(child's text) 
     else getTextContent(child, sb); 
    } 
    return sb; 
} 
0

嗯,我几乎没有与代码...

public String getParam1(Document d) { 
    if (d.getDocumentElement().getTagName().equals("AmigoRequest")) { 
     NodeList results = d.getElementsByTagName("Param1"); 
     // Messagetype depends on what message we are reading.   
     if (results.getLength() > 0 && results != null) {     
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
      DocumentBuilder db; 
      Element node = (Element) results.item(0); // get the value of Param1 
      Document doc2 = null; 
      try { 

       db = dbf.newDocumentBuilder(); 
       doc2 = db.newDocument(); //create new document 
       doc2.appendChild(doc2.importNode(node, true)); //import the <html>...</html> result in doc2 

      } catch (ParserConfigurationException e) { 
       // TODO Auto-generated catch block 
       Log.d(TAG, " Exception ", e); 
      } catch (DOMException e) { 
       // TODO: handle exception 
       Log.d(TAG, " Exception ", e); 
      } catch (Exception e) { 
       // TODO: handle exception 
       e.printStackTrace();    }    


      return doc2. .....// All I'm missing is something to convert a Document to a string. 
     } 
    } 
    return ""; 

} 

就像我的代码的评论中所解释的那样。我所缺少的是从文档中创建一个字符串。你不能使用Android中的变换类... doc2.toString()会给你一个对象的序列化..

但是,我的下一步是写我自己的解析器,如果这没有解决;)

不是最好的代码,而是一个短暂的解决方案。

public String getParam1(String b) { 
     return b 
       .substring(b.indexOf("<Param1>") + "<Param1>".length(), b.indexOf("</Param1>")); 
    } 

其中string b为XML文档的字符串。

1

检查了很多,刮的时候我的头数千后,我想出了简单的改动,它需要改变你的API等级8