ฉันจะส่งออก org.w3c.dom.Element ในรูปแบบสตริงใน java ได้อย่างไร


90

ฉันมีorg.w3c.dom.Elementวัตถุที่ส่งเข้ามาในวิธีการของฉัน ฉันต้องการดูสตริง xml ทั้งหมดรวมถึงโหนดลูก (กราฟวัตถุทั้งหมด) ฉันกำลังมองหาวิธีการที่สามารถแปลงElementเป็นสตริงรูปแบบ XML ที่ฉันสามารถทำได้System.out.printlnบน เพียงแค่println()บนวัตถุ 'องค์ประกอบ' จะไม่ทำงานเนื่องจากtoString()จะไม่ส่งออกรูปแบบ xml และจะไม่ผ่านโหนดลูก มีวิธีง่ายๆโดยไม่ต้องเขียนวิธีการของตัวเองหรือไม่? ขอบคุณ.

คำตอบ:


156

สมมติว่าคุณต้องการใช้ API มาตรฐาน ...

คุณสามารถใช้DOMImplementationLS :

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

หากการประกาศ <? xml version = "1.0" encoding = "UTF-16"?> รบกวนคุณคุณสามารถใช้หม้อแปลงแทน:

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();

7
นี่เป็นวิธีแก้ปัญหาหากคุณได้รับ [html: null] และคาดหวัง HTML เพิ่มความคิดเห็นนี้เพื่อให้ Google สามารถจัดทำดัชนีคำตอบได้
Donal Tobin

3
คุณยังสามารถใช้ LSSerializer และเอาต์พุต "UTF-8" ได้ ใช้ LSOutput กับ StringWriter แทนและตั้งค่าประเภทการเข้ารหัสเป็น "UTF- * 8"
ricosrealm

1
ทำงานร่วมกับวัตถุ w3c Document ได้เช่นกัน
thirdy

2
<?xml version="1.0" encoding="UTF-16"?>คำประกาศรบกวน ... เราสามารถเพิ่มบรรทัดนี้serializer .getDomConfig().setParameter("xml-declaration", false); ในโซลูชันแรกได้ ....
Tarsem Singh

ขอบคุณสำหรับคำตอบของคุณเยี่ยมมาก แต่ฉันมีปัญหากับมันบางครั้งแท็กบางส่วนของส่วนที่ตรงกันจะถูกลบออกและเนื้อหาข้อความของพวกเขาจะปรากฏขึ้นเพียงอย่างเดียว คุณมีคำแนะนำสำหรับปัญหานี้หรือไม่?
epcpu

16

รหัส 4 บรรทัดอย่างง่ายที่จะได้รับString โดยไม่ต้องประกาศ xml ( <?xml version="1.0" encoding="UTF-16"?>) จาก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);

2

ไม่รองรับ JAXP API มาตรฐานฉันใช้ไลบรารี JDom เพื่อจุดประสงค์นี้ มีฟังก์ชันเครื่องพิมพ์ตัวเลือกฟอร์แมตเตอร์ ฯลฯhttp://www.jdom.org/


+1 เนื่องจากไม่ได้เป็นเจตนาของ org.w3c.dom API มาตรฐาน หากฉันสนใจบล็อก XML เป็นข้อความฉันมักจะพยายามแยกวิเคราะห์ออกมาเป็นข้อความด้วยการจับคู่นิพจน์ทั่วไป (หากเกณฑ์การค้นหาแสดงเป็นนิพจน์ทั่วไปได้อย่างง่ายดาย)
Cornel Masson

2

หากคุณมีสคีมาของ XML หรือสามารถสร้างการเชื่อมโยง JAXB ได้คุณสามารถใช้ JAXB Marshaller เพื่อเขียนไปยัง 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);
    }
}

2

ลองjcabi-xmlด้วยซับเดียว:

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

jcabi-xml เวอร์ชันใหม่ไม่รองรับ Element เป็นพารามิเตอร์เฉพาะ Node / File / String
Ermintar

1

นี่คือสิ่งที่ทำใน 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();
}

และมันได้ผลสำหรับฉัน!


0

ด้วยVTD-XMLคุณสามารถส่งผ่านไปยังเคอร์เซอร์และทำการเรียก getElementFragment เพียงครั้งเดียวเพื่อดึงเซ็กเมนต์ (ตามที่แสดงด้วยออฟเซ็ตและความยาว) ... ด้านล่างนี้คือตัวอย่าง

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)));
        }
    }

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.