【问题标题】:Android: Parsing XML DOM parser. Converting childnodes to stringAndroid:解析 XML DOM 解析器。将子节点转换为字符串
【发布时间】:2011-01-04 06:38:56
【问题描述】:

又是一个问题。这次我正在解析从服务器接收到的 XML 消息。 有人认为自己很聪明,决定将 HTML 页面放在 XML 消息中。现在我有点面临问题,因为我想从这个 XML 消息中提取那个 HTML 页面作为字符串。

好的,这是我正在解析的 XML 消息:

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

您会看到在 Param1 中指定了一个 HTML 页面。我尝试通过以下方式提取消息:

公共字符串 getParam1(文档 d){ if (d.getDocumentElement().getTagName().equals("AmigoRequest")) { NodeList 结果 = d.getElementsByTagName("Param1"); // 消息类型取决于我们正在阅读的消息。 if (results.getLength() > 0 && results != null) { 返回结果.item(0).getFirstChild().getNodeValue(); } } 返回 ””; }

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

如何从字符串中的 Param0 中提取 html 消息 &lt;html&gt;&lt;head&gt;test&lt;/head&gt;&lt;body&gt;Testhtml&lt;/body&gt;&lt;/html&gt;

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

感谢您的宝贵时间和回复。

安泰克

【问题讨论】:

  • 可以选择 XPath 吗?如果是这样,我也许可以为您提供帮助,而且我从未使用过 andriod,这就是我问的原因。
  • XPath 不受支持,但我设法通过使用 DOM4J 和 Jaxen 找到了适用于 Android 的解决方法。

标签: java xml android parsing domparser


【解决方案1】:

您可以像这样获取 param1 的内容:

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

【讨论】:

  • 太糟糕了,Android 不支持 getTextContent 函数。 Android 正在使用旧的 dom 解析器。但我现在也知道在哪里看。仍然没有找到该主题的解决方案,但我已经编辑了我的主题标题。
  • 如果getTextContent 在平台上可用,那么调用它就足够了,而无需围绕它进行extractHTMLTags 调用。 getTextContent 从返回的字符串中去除任何 XML 标记(更准确地说,它通过连接嵌套元素内的所有文本字符串来获取其值,同时留下元素标签。)当然,这确实假设 HTML 内容是格式良好的 XML。但如果不是,您可能甚至无法在 XML 解析中达到这一点。
  • 哦,我没用过android,也不知道它的DOM解析器!我以为它使用的是最新版本。很抱歉!
  • 不,Alex,不要抱歉 :) 你帮助我朝着正确的方向前进,我发现了一些关于 Androids dom 解析器的有用信息。似乎它只能提取文本节点。我目前正在研究所有其他 cmets。
【解决方案2】:

在检查了很多并摸不着头脑之后,我想出了一个简单的改动,它需要将你的 API 级别更改为 8

【讨论】:

    【解决方案3】:

    编辑:我刚刚看到您在上面关于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) {                
    

    否则,如果 results 确实以 null 的形式返回,您将获得 NPE。

    【讨论】:

      【解决方案4】:

      由于您无法使用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;
      }
      

      【讨论】:

        【解决方案5】:

        好吧,我几乎已经有了代码......

        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 中使用 Transform 类... doc2.toString() 将为您提供对象的序列化..

        但如果这不起作用,我的下一步是编写自己的解析器;)

        不是最好的代码,而是临时解决方案。

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

        其中 String b 是 XML 文档字符串。

        【讨论】:

          猜你喜欢
          • 2013-11-08
          • 1970-01-01
          • 1970-01-01
          • 2011-11-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多