Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
获取一个节点';Java DOM中的内部XML作为字符串_Java_Xml_Dom - Fatal编程技术网

获取一个节点';Java DOM中的内部XML作为字符串

获取一个节点';Java DOM中的内部XML作为字符串,java,xml,dom,Java,Xml,Dom,我有一个XML org.w3c.dom.Node,看起来像这样: <variable name="variableName"> <br /><strong>foo</strong> bar </variable> ByteArrayOutputStream out = new ByteArrayOutputStream(); Transformer transformer = TransformerFactory.newIns

我有一个XML org.w3c.dom.Node,看起来像这样:

<variable name="variableName">
    <br /><strong>foo</strong> bar
</variable>
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();


foo酒吧

如何将

foo
部分作为字符串获取?

org.w3c.dom.Node
上没有简单的方法可以实现这一点
getTextContent()
提供连接在一起的每个子节点的文本<如果当前节点是
属性
CDATA
文本
节点,则code>getNodeValue()将为您提供当前节点的文本。因此,您需要使用
getChildNodes()
getNodeName()
getNodeValue()
组合来序列化节点以构建字符串


您还可以使用现有的各种XML序列化库之一来实现这一点。有
XStream
甚至还有JAXB。这里讨论这个问题:

同样的问题。为了解决这个问题,我编写了这个helper函数:

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(); 
}
公共字符串innerXml(节点){
domImplementals lsImpl=(domImplementals)node.getOwnerDocument().getImplementation().getFeature(“LS”,“3.0”);
LSSerializer LSSerializer=lsImpl.createLSSerializer();
NodeList childNodes=node.getChildNodes();
StringBuilder sb=新的StringBuilder();
对于(int i=0;i
如果您不想求助于外部库,以下解决方案可能会派上用场。如果您有一个节点
,并且希望提取父元素的子元素,请按以下步骤进行操作:

    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();
StringBuilder resultBuilder=new StringBuilder();
//获取给定父节点的所有子节点
nodelistchildrends=parent.getChildNodes();
试一试{
//设置输出变压器
TransformerFactory transfac=TransformerFactory.newInstance();
变压器变压器=变压器新变压器();
trans.setOutputProperty(OutputKeys.OMIT_XML_声明,“yes”);
trans.setOutputProperty(OutputKeys.INDENT,“是”);
StringWriter StringWriter=新StringWriter();
StreamResult StreamResult=新的StreamResult(stringWriter);
对于(int index=0;index
如果您正在使用,您可以用类似的语法包装节点,只需在其上调用
toString()

$(node).toString();
它在内部使用标识转换器,如下所示:

<variable name="variableName">
    <br /><strong>foo</strong> bar
</variable>
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();

基于Lukas Eder的解决方案,我们可以像在.NET中一样提取innerXml,如下所示

    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;               
}
公共静态字符串innerXml(节点,字符串标记){
字符串xmlstring=toString(节点);
xmlstring=xmlstring.replaceFirst(“,”);
返回xmlstring;
}
公共静态字符串到字符串(节点){
字符串xmlString=“”;
变压器;
试一试{
transformer=TransformerFactory.newInstance().newTransformer();
setOutputProperty(OutputKeys.OMIT_XML_声明,“yes”);
//transformer.setOutputProperty(OutputKeys.INDENT,“是”);
StreamResult=新的StreamResult(新的StringWriter());
xmlString=nodeToStream(节点、转换器、结果);
}捕获(TransformerConfiguration异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(TransformerFactoryConfigurationError e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(转换异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(例外情况除外){
例如printStackTrace();
}
返回xmlString;
}
例:

如果节点名称指向具有字符串表示形式“ChristianBale”的xml
字符串innerXml=innerXml(名称,“name”)//返回“ChristianBale”

我对上一个答案有一个问题,即方法“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;
}

根据Andrey M的回答,我不得不稍微修改代码以获得完整的DOM文档。如果你只是使用

 NodeList childNodes = node.getChildNodes();
它没有为我包含根元素。为了包含根元素(并获取完整的.xml文档),我使用了:


下面是提取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;
}
私有静态字符串innerXml(节点节点)抛出TransformerFactoryConfigurationError,TransformerException{
StringWriter编写器=新的StringWriter();
字符串xml=null;
Transformer Transformer=TransformerFactory.newInstance().newTransformer();
setOutputProperty(OutputKeys.OMIT_XML_声明,“yes”);
transform(新的DOMSource(节点)、新的StreamResult(writer));
//现在移除外部标记。。。。
xml=writer.toString();

xml=xml.substring(xml.indexOf(“>”)+1,xml.lastIndexOf(“到目前为止最好的解决方案,Andrey M的,需要一个特定的实现,这可能会在将来引起问题。这里是相同的方法,但只要JDK给您提供什么,就可以进行序列化(这意味着配置要使用什么)


如果我建议使用一个库来处理这个问题,可以试试JSoup,它主要用于HTML,但我还没有测试过

Document doc = Jsoup.parse(xml, "", Parser.xmlParser());
fileContents.put(Attributes.BODY, document.body().html());
// versus: document.body().outerHtml()

我想扩展Andrey M.的非常好的回答:

节点可能不可序列化,这会导致某些实现出现以下异常:

org.w3c.dom.ls.LSException: unable-to-serialize-node: 
            unable-to-serialize-node: The node could not be serialized.
我在实现“org.apache.xml.s”时遇到了这个问题
Document doc = Jsoup.parse(xml, "", Parser.xmlParser());
fileContents.put(Attributes.BODY, document.body().html());
// versus: document.body().outerHtml()
org.w3c.dom.ls.LSException: unable-to-serialize-node: 
            unable-to-serialize-node: The node could not be serialized.
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();
}