Как получить содержимое узла из JDOM - PullRequest
6 голосов
/ 27 октября 2011

Я пишу приложение в Java, используя импорт org.jdom. *;

Мой XML допустим, но иногда он содержит теги HTML. Например, что-то вроде этого:

  <program-title>Anatomy &amp; Physiology</program-title>
  <overview>
       <content>
              For more info click <a href="page.html">here</a>
              <p>Learn more about the human body.  Choose from a variety of Physiology (A&amp;P) designed for complementary therapies.&amp;#160; Online studies options are available.</p>
       </content>
  </overview>
  <key-information>
     <category>Health &amp; Human Services</category>

Так что моя проблема с тегами

внутри узла Overview.content.

Я надеялся, что этот код будет работать:

        Element overview = sds.getChild("overview");
        Element content = overview.getChild("content");

        System.out.println(content.getText());

но возвращается пустым.

Как вернуть весь текст (вложенные теги и все) из узла Overview.content?

Спасибо

Ответы [ 7 ]

16 голосов
/ 13 января 2012

content.getText() дает немедленный текст, который полезен только с листовыми элементами с текстовым содержимым.

Хитрость заключается в использовании org.jdom.output.XMLOutputter (в текстовом режиме CompactFormat)

public static void main(String[] args) throws Exception {
    SAXBuilder builder = new SAXBuilder();
    String xmlFileName = "a.xml";
    Document doc = builder.build(xmlFileName);

    Element root = doc.getRootElement();
    Element overview = root.getChild("overview");
    Element content = overview.getChild("content");

    XMLOutputter outp = new XMLOutputter();

    outp.setFormat(Format.getCompactFormat());
    //outp.setFormat(Format.getRawFormat());
    //outp.setFormat(Format.getPrettyFormat());
    //outp.getFormat().setTextMode(Format.TextMode.PRESERVE);

    StringWriter sw = new StringWriter();
    outp.output(content.getContent(), sw);
    StringBuffer sb = sw.getBuffer();
    System.out.println(sb.toString());
}

выход

For more info click<a href="page.html">here</a><p>Learn more about the human body. Choose from a variety of Physiology (A&amp;P) designed for complementary therapies.&amp;#160; Online studies options are available.</p>

Изучите другие опции форматирования и измените приведенный выше код под свои нужды.

"Класс для инкапсуляции параметров формата XMLOutputter. Обычные пользователи могут использовать стандартные конфигурации формата, полученные с помощью getRawFormat () (без изменения пробелов), getPrettyFormat () (украшение пробелов) и getCompactFormat () (нормализация пробелов)."

4 голосов
/ 27 октября 2011

Вы можете попробовать использовать метод getValue () для ближайшего приближения, но это объединяет весь текст в элементе и потомках вместе.Это не даст вам тег <p> в любой форме.Если этот тег находится в вашем XML, как вы показали, он стал частью разметки XML.Он должен быть включен как &lt;p&gt; или встроен в раздел CDATA, чтобы рассматриваться как текст.

В качестве альтернативы, если вы знаете все элементы, которые могут или не могут появиться в вашем XML, вы можете применитьXSLT-преобразование, которое превращает материал, который не предназначен для разметки, в простой текст.

3 голосов
/ 17 января 2012

Ну, может быть, это то, что вам нужно:

import java.io.StringReader;

import org.custommonkey.xmlunit.XMLTestCase;
import org.custommonkey.xmlunit.XMLUnit;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.testng.annotations.Test;
import org.xml.sax.InputSource;

public class HowToGetNodeContentsJDOM extends XMLTestCase
{
    private static final String XML = "<root>\n" + 
            "  <program-title>Anatomy &amp; Physiology</program-title>\n" + 
            "  <overview>\n" + 
            "       <content>\n" + 
            "              For more info click <a href=\"page.html\">here</a>\n" + 
            "              <p>Learn more about the human body.  Choose from a variety of Physiology (A&amp;P) designed for complementary therapies.&amp;#160; Online studies options are available.</p>\n" + 
            "       </content>\n" + 
            "  </overview>\n" + 
            "  <key-information>\n" + 
            "     <category>Health &amp; Human Services</category>\n" + 
            "  </key-information>\n" + 
            "</root>";
    private static final String EXPECTED = "For more info click <a href=\"page.html\">here</a>\n" + 
            "<p>Learn more about the human body.  Choose from a variety of Physiology (A&amp;P) designed for complementary therapies.&amp;#160; Online studies options are available.</p>";

    @Test
    public void test() throws Exception
    {
        XMLUnit.setIgnoreWhitespace(true);
        Document document = new SAXBuilder().build(new InputSource(new StringReader(XML)));
        List<Content> content = document.getRootElement().getChild("overview").getChild("content").getContent();
        String out = new XMLOutputter().outputString(content);
        assertXMLEqual("<root>" + EXPECTED + "</root>", "<root>" + out + "</root>");
    }
}

Выход:

PASSED: test on instance null(HowToGetNodeContentsJDOM)

===============================================
    Default test
    Tests run: 1, Failures: 0, Skips: 0
===============================================

Я использую JDom с генериками: http://www.junlu.com/list/25/883674.html

Редактировать: На самом деле это не сильно отличается от ответа Прашанта Бхате. Может быть, вы должны сказать нам, что вам не хватает ...

1 голос
/ 18 января 2012

Если вы также генерируете файл XML, вы должны иметь возможность инкапсулировать ваши HTML-данные в <![CDATA[]]>, чтобы они не анализировались синтаксическим анализатором XML.

0 голосов
/ 15 сентября 2016

Если вы хотите вывести содержимое некоторого узла JSOM, просто используйте

System.out.println(new XMLOutputter().outputString(node))
0 голосов
/ 17 января 2012

Не особо красиво, но отлично работает (используя JDOM API):

public static String getRawText(Element element) {
    if (element.getContent().size() == 0) {
        return "";
    }

    StringBuffer text = new StringBuffer();
    for (int i = 0; i < element.getContent().size(); i++) {
        final Object obj = element.getContent().get(i);
        if (obj instanceof Text) {
            text.append( ((Text) obj).getText() );
        } else if (obj instanceof Element) {
            Element e = (Element) obj;
            text.append( "<" ).append( e.getName() );
            // dump all attributes
            for (Attribute attribute : (List<Attribute>)e.getAttributes()) {
                text.append(" ").append(attribute.getName()).append("=\"").append(attribute.getValue()).append("\"");
            }
            text.append(">");
            text.append( getRawText( e )).append("</").append(e.getName()).append(">");
        }
    }
    return text.toString();
}

Решение Prashant Bhate лучше, хотя!

0 голосов
/ 27 октября 2011

Проблема в том, что у узла <content> нет текстового дочернего элемента; у него есть <p> дочерний элемент, который содержит текст.

Попробуйте это:

Element overview = sds.getChild("overview");
Element content = overview.getChild("content");
Element p = content.getChild("p");
System.out.println(p.getText());

Если вы хотите, чтобы все непосредственные дочерние узлы вызывались p.getChildren(). Если вы хотите получить ВСЕ дочерние узлы, вам придется вызывать его рекурсивно.

...