Получить внутренний XML-код узла в виде строки в Java DOM - PullRequest
25 голосов
/ 21 июля 2010

У меня есть XML org.w3c.dom.Node, который выглядит следующим образом:

<variable name="variableName">
    <br /><strong>foo</strong> bar
</variable>

Как мне получить <br /><strong>foo</strong> bar часть в виде строки?

Ответы [ 10 ]

43 голосов
/ 10 мая 2011

Та же проблема.Чтобы решить эту проблему, я написал эту вспомогательную функцию:

public String innerXml(Node node) {
    DOMImplementationLS lsImpl = (DOMImplementationLS)node.getOwnerDocument().getImplementation().getFeature("LS", "3.0");
    LSSerializer lsSerializer = lsImpl.createLSSerializer();
    NodeList childNodes = node.getChildNodes();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < childNodes.getLength(); i++) {
       sb.append(lsSerializer.writeToString(childNodes.item(i)));
    }
    return sb.toString(); 
}
6 голосов
/ 25 июля 2010

Нет простого метода для org.w3c.dom.Node для этого.getTextContent() дает текст каждого дочернего узла, объединенного вместе.getNodeValue() выдаст вам текст текущего узла, если это узел Attribute, CDATA или Text.Таким образом, вам нужно будет сериализовать узел, используя комбинацию getChildNodes(), getNodeName() и getNodeValue() для построения строки.

Вы также можете сделать это с одной из различных существующих библиотек сериализации XML.Есть XStream или даже JAXB.Это обсуждается здесь: XML-сериализация в Java?

4 голосов
/ 22 января 2012

Если вы используете jOOX , вы можете обернуть свой узел в jquery -подобный синтаксис и просто вызвать toString() для него:

$(node).toString();

Внутри используется идентификатор-преобразователь, например:

ByteArrayOutputStream out = new ByteArrayOutputStream();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
Source source = new DOMSource(element);
Result target = new StreamResult(out);
transformer.transform(source, target);
return out.toString();
2 голосов
/ 19 января 2017

Продолжая ответ Андрея М, мне пришлось немного изменить код, чтобы получить полный документ DOM. Если вы просто используете

 NodeList childNodes = node.getChildNodes();

Это не включает в себя корневой элемент для меня. Чтобы включить корневой элемент (и получить полный XML-документ), я использовал:

 public String innerXml(Node node) {
     DOMImplementationLS lsImpl = (DOMImplementationLS)node.getOwnerDocument().getImplementation().getFeature("LS", "3.0");
     LSSerializer lsSerializer = lsImpl.createLSSerializer();
     lsSerializer.getDomConfig().setParameter("xml-declaration", false);
     StringBuilder sb = new StringBuilder();
     sb.append(lsSerializer.writeToString(node));
     return sb.toString(); 
 }
2 голосов
/ 02 января 2012

Если вы не хотите использовать внешние библиотеки, вам может пригодиться следующее решение.Если у вас есть узел <parent><child name="Nina"/></parent> и вы хотите извлечь дочерние элементы родительского элемента, выполните следующие действия:

    StringBuilder resultBuilder = new StringBuilder();
    // Get all children of the given parent node
    NodeList children = parent.getChildNodes();
    try {

        // Set up the output transformer
        TransformerFactory transfac = TransformerFactory.newInstance();
        Transformer trans = transfac.newTransformer();
        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        trans.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter stringWriter = new StringWriter();
        StreamResult streamResult = new StreamResult(stringWriter);

        for (int index = 0; index < children.getLength(); index++) {
            Node child = children.item(index);

            // Print the DOM node
            DOMSource source = new DOMSource(child);
            trans.transform(source, streamResult);
            // Append child to end result
            resultBuilder.append(stringWriter.toString());
        }
    } catch (TransformerException e) {
        //Error handling goes here
    }
    return resultBuilder.toString();
1 голос
/ 29 августа 2014

У меня была проблема с последним ответом, что метод 'nodeToStream ()' не определен;следовательно, моя версия здесь:

    public static String toString(Node node){
    String xmlString = "";
    try {
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        //transformer.setOutputProperty(OutputKeys.INDENT, "yes");

        Source source = new DOMSource(node);

        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);

        transformer.transform(source, result);
        xmlString = sw.toString ();

    } catch (Exception ex) {
        ex.printStackTrace ();
    }

    return xmlString;
}
0 голосов
/ 05 августа 2018

Хочу расширить очень хороший ответ от Андрея М .:

Может случиться, что узел не сериализуем, и это приводит к следующему исключению в некоторых реализациях:

org.w3c.dom.ls.LSException: unable-to-serialize-node: 
            unable-to-serialize-node: The node could not be serialized.

У меня была эта проблема с реализацией " org.apache.xml.serialize.DOMSerializerImpl.writeToString (DOMSerializerImpl) ", работающей на Wildfly 13.

Чтобы решить эту проблему, я бы предложил немного изменить пример кода от Андрея М.:

private static String innerXml(Node node) {
    DOMImplementationLS lsImpl = (DOMImplementationLS) node.getOwnerDocument().getImplementation().getFeature("LS", "3.0");
    LSSerializer lsSerializer = lsImpl.createLSSerializer();
    lsSerializer.getDomConfig().setParameter("xml-declaration", false); 
    NodeList childNodes = node.getChildNodes();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < childNodes.getLength(); i++) {
        Node innerNode = childNodes.item(i);
        if (innerNode!=null) {
            if (innerNode.hasChildNodes()) {
                sb.append(lsSerializer.writeToString(innerNode));
            } else {
                sb.append(innerNode.getNodeValue());
            }
        }
    }
    return sb.toString();
}

Я также добавил комментарий от Nyerguds. Это работает для меня в wildfly 13.

0 голосов
/ 30 июля 2018

Наилучшее решение, Андрей М, нуждается в конкретной реализации, которая может вызвать проблемы в будущем. Здесь тот же подход, но только с тем, что JDK дает вам для сериализации (это означает, что настроено для использования).

public static String innerXml(Node node) throws Exception
{
        StringWriter writer = new StringWriter();
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

        NodeList childNodes = node.getFirstChild().getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            transformer.transform(new DOMSource(childNodes.item(i)), new StreamResult(writer));
        }
        return writer.toString();
}

Если вы обрабатываете документ , а не узел, вы должны углубиться на один уровень и использовать node.getFirstChild().getChildNodes(); Но, , чтобы сделать его более надежным, вы должны найти Первый элемент, а не просто принимать как должное, что есть только один узел. XML должен иметь один корневой элемент, но может содержать несколько узлов, включая комментарии, сущности и пробельные символы.

        Node rootElement = docRootNode.getFirstChild();
        while (rootElement != null && rootElement.getNodeType() != Node.ELEMENT_NODE)
            rootElement = rootElement.getNextSibling();
        if (rootElement == null)
            throw new RuntimeException("No root element found in given document node.");

        NodeList childNodes = rootElement.getChildNodes();

И если мне порекомендовать библиотеку для работы с ней, попробуйте JSoup, который в основном предназначен для HTML, но также работает с XML . Хотя я этого не проверял.

Document doc = Jsoup.parse(xml, "", Parser.xmlParser());
fileContents.put(Attributes.BODY, document.body().html());
// versus: document.body().outerHtml()
0 голосов
/ 25 февраля 2017

Вот альтернативное решение для извлечения содержимого org.w3c.dom.Node. Это решение также работает, если содержимое узла не содержит тегов xml:

private static String innerXml(Node node) throws TransformerFactoryConfigurationError, TransformerException {
    StringWriter writer = new StringWriter();
    String xml = null;
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    transformer.transform(new DOMSource(node), new StreamResult(writer));
    // now remove the outer tag....
    xml = writer.toString();
    xml = xml.substring(xml.indexOf(">") + 1, xml.lastIndexOf("</"));
    return xml;
}
0 голосов
/ 03 января 2014

Основываясь на решении Лукаса Эдера, мы можем извлечь innerXml, как в .NET, как показано ниже

    public static String innerXml(Node node,String tag){
            String xmlstring = toString(node);
            xmlstring = xmlstring.replaceFirst("<[/]?"+tag+">","");
            return xmlstring;       
}

public static String toString(Node node){       
    String xmlString = "";
    Transformer transformer;
    try {
        transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        //transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StreamResult result = new StreamResult(new StringWriter());

        xmlString = nodeToStream(node, transformer, result);

    } catch (TransformerConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (TransformerFactoryConfigurationError e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (TransformerException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }catch (Exception ex){
        ex.printStackTrace();
    }

    return xmlString;               
}

Пример:

If Node name points to xml with string representation "<Name><em>Chris</em>tian<em>Bale</em></Name>" 
String innerXml = innerXml(name,"Name"); //returns "<em>Chris</em>tian<em>Bale</em>"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...