Android: парсер XML DOM. Преобразование дочерних узлов в строку - PullRequest
2 голосов
/ 12 января 2010

опять вопрос. На этот раз я анализирую XML-сообщения, полученные от сервера. Кто-то считал себя умным и решил поместить HTML-страницы в сообщение XML. Теперь у меня возникли некоторые проблемы, потому что я хочу извлечь эту HTML-страницу в виде строки из этого XML-сообщения.

Хорошо, это 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-страница. Я попытался извлечь сообщение следующим образом:

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 () возвращает нулевое значение. Когда я пытаюсь использовать results.item (0) .getFirstChild (). HasChildNodes (), он возвращает true, потому что видит, что в сообщении есть тег.

Как извлечь html-сообщение <html><head>test</head><body>Testhtml</body></html> из Param0 в строку?

Я использую Android SDK 1.5 (почти Java) и DOM Parser.

Спасибо за ваше время и ответы.

Антек

Ответы [ 5 ]

1 голос
/ 31 января 2011

после много проверок и почесывания головы тысячи раз я придумал простое изменение, которое должно изменить уровень API на 8

1 голос
/ 12 января 2010

Вы можете взять содержимое 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-тега из строки. Для этого вы можете взглянуть на этот пост: Удалить HTML-теги из строки

0 голосов
/ 13 января 2010

Ну, я был почти там с кодом ...

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

}

Как объяснено в комментарии к моему коду. Все, чего мне не хватает, это сделать строку из документа. Вы не можете использовать класс Transform в Android ... doc2.toString () даст вам сериализацию объекта ..

Но мой следующий шаг - написать свой собственный парсер, если это не сработает;)

Не лучший код, но временное решение.

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

Где String b - строка документа XML.

0 голосов
/ 12 января 2010

Поскольку getTextContent() недоступен для вас, можно написать еще один вариант - это не сложно. На самом деле, если вы пишете это исключительно для собственного использования - или у вашего работодателя нет слишком строгих правил в отношении открытого исходного кода - вы можете рассматривать реализацию Apache как отправную точку; строки 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 голосов
/ 12 января 2010

РЕДАКТИРОВАТЬ : Я только что видел ваш комментарий выше о том, что 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() - это вызов API DOM уровня 3; не все парсеры гарантированно поддерживают его. Xerces-J делает .

Кстати, в вашем первоначальном примере ваш чек на null находится не в том месте; должно быть:

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

В противном случае вы получите NPE, если results действительно вернется как null.

...