如何在 java 中将 org.w3c.dom. Element 输出为字符串格式?

我有一个 org.w3c.dom.Element对象传递到我的方法。我需要查看整个 xml 字符串,包括它的子节点(整个对象图)。我正在寻找一个方法,可以转换的 Element到一个 xml 格式的字符串,我可以 System.out.println上。仅仅在‘ Element’对象上使用 println()是不行的,因为 toString()不会输出 xml 格式,也不会遍历它的子节点。有没有一种简单的方法不用写我自己的方法就可以做到这一点?谢谢。

102431 次浏览

Not supported in the standard JAXP API, I used the JDom library for this purpose. It has a printer function, formatter options etc. http://www.jdom.org/

Assuming you want to stick with the standard API...

You could use a DOMImplementationLS:

Document document = node.getOwnerDocument();
DOMImplementationLS domImplLS = (DOMImplementationLS) document
.getImplementation();
LSSerializer serializer = domImplLS.createLSSerializer();
String str = serializer.writeToString(node);

If the <?xml version="1.0" encoding="UTF-16"?> declaration bothers you, you could use a transformer instead:

TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
StringWriter buffer = new StringWriter();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(node),
new StreamResult(buffer));
String str = buffer.toString();

If you have the schema of the XML or can otherwise create JAXB bindings for it, you could use the JAXB Marshaller to write to System.out:

import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;


@XmlRootElement
public class BoundClass {


@XmlAttribute
private String test;


@XmlElement
private int x;


public BoundClass() {}


public BoundClass(String test) {
this.test = test;
}


public static void main(String[] args) throws Exception {
JAXBContext jxbc = JAXBContext.newInstance(BoundClass.class);
Marshaller marshaller = jxbc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.marshal(new JAXBElement(new QName("root"),BoundClass.class,new Main("test")),System.out);
}
}

Simple 4 lines code to get String without xml-declaration (<?xml version="1.0" encoding="UTF-16"?>) from org.w3c.dom.Element

DOMImplementationLS lsImpl = (DOMImplementationLS)node.getOwnerDocument().getImplementation().getFeature("LS", "3.0");
LSSerializer serializer = lsImpl.createLSSerializer();
serializer.getDomConfig().setParameter("xml-declaration", false); //by default its true, so set it to false to get String without xml-declaration
String str = serializer.writeToString(node);

Try jcabi-xml with one liner:

String xml = new XMLDocument(element).toString();

With VTD-XML, you can pass into the cursor and make a single getElementFragment call to retrieve the segment (as denoted by its offset and length)... Below is an example

import com.ximpleware.*;
public class concatTest{
public static void main(String s1[]) throws Exception {
VTDGen vg= new VTDGen();
String s = "<users><user><firstName>some </firstName><lastName> one</lastName></user></users>";
vg.setDoc(s.getBytes());
vg.parse(false);
VTDNav vn = vg.getNav();
AutoPilot ap = new AutoPilot(vn);
ap.selectXPath("/users/user/firstName");
int i=ap.evalXPath();
if (i!=1){
long l= vn.getElementFragment();
System.out.println(" the segment is "+ vn.toString((int)l,(int)(l>>32)));
}
}


}

this is what i s done in jcabi:

private String asString(Node node) {
StringWriter writer = new StringWriter();
try {
Transformer trans = TransformerFactory.newInstance().newTransformer();
// @checkstyle MultipleStringLiterals (1 line)
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty(OutputKeys.VERSION, "1.0");
if (!(node instanceof Document)) {
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
}
trans.transform(new DOMSource(node), new StreamResult(writer));
} catch (final TransformerConfigurationException ex) {
throw new IllegalStateException(ex);
} catch (final TransformerException ex) {
throw new IllegalArgumentException(ex);
}
return writer.toString();
}

and it works for me!