Làm cách nào để chuyển đổi một đối tượng org.w3c.dom.Document thành một Chuỗi?


87

Tôi muốn chuyển đổi đối tượng org.w3c.dom.Document thành Chuỗi. Tôi đang sử dụng Java 6 và sẵn sàng sử dụng bất kỳ công nghệ nào (hoàn toàn miễn phí) tùy theo nhiệm vụ. Tôi đã thử giải pháp từ luồng này - Có cách nào thanh lịch hơn để chuyển đổi Tài liệu XML thành Chuỗi trong Java hơn mã này không? , nơi họ có

DOMImplementationLS domImplementation = (DOMImplementationLS) doc.getImplementation();
LSSerializer lsSerializer = domImplementation.createLSSerializer();
String html = lsSerializer.writeToString(doc);  

nhưng đã được chào đón bằng một ngoại lệ khủng khiếp sau đây…

org.w3c.dom.DOMException: DOM method not supported
    at org.w3c.tidy.DOMDocumentImpl.getImplementation(DOMDocumentImpl.java:129)
    at com.myco.myproj.cleaners.JTidyCleaner.outputDocAsString(JTidyCleaner.java:74)
    at com.myco.myproj.cleaners.JTidyCleaner.parse(JTidyCleaner.java:63)
    at com.myco.myproj.util.NetUtilities.getUrlAsDocument(NetUtilities.java:51)
    at com.myco.myproj.parsers.AbstractHTMLParser.getEventFromElement(AbstractHTMLParser.java:131)
    at com.myco.myproj.parsers.AbstractHTMLParser.parsePage(AbstractHTMLParser.java:100)
    at com.myco.myproj.parsers.AbstractHTMLParser.getEvents(AbstractHTMLParser.java:63)
    at com.myco.myproj.domain.EventFeed.refresh(EventFeed.java:87)
    at com.myco.myproj.domain.EventFeed.getEvents(EventFeed.java:72)
    at com.myco.myproj.parsers.impl.ChicagoCouncilGlobalAffairsParserTest.testParser(ChicagoCouncilGlobalAffairsParserTest.java:21)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

chuyển đổi danh tính ( en.wikipedia.org/wiki/Identity_transform ) là cách tốt nhất của bạn nếu bạn không muốn phụ thuộc vào một số loại tuần tự. Hai câu trả lời được đưa ra đã làm được điều đó. Chạy một biến đổi trống rỗng như vậy thì danh tính sẽ biến đổi đằng sau hậu trường.
Pavel Veller

Câu trả lời:


88

Nếu bạn có thể thực hiện chuyển đổi, bạn có thể thử điều này.

DocumentBuilderFactory domFact = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFact.newDocumentBuilder();
Document doc = builder.parse(st);
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
System.out.println("XML IN String format is: \n" + writer.toString());

Bất kỳ ý tưởng làm thế nào để viết JUnits cho đoạn mã trên? Tôi nhận được một verifyError trong khi viết như vậy. Tôi đã hỏi một câu hỏi bằng SO, nếu bạn rảnh, vui lòng trả lời. stackoverflow.com/q/48560458/5989309
Alan Pallath

2
Tôi sẽ không viết một bài kiểm tra đơn vị cho mã như vậy. Bạn sẽ kiểm tra hệ thống ống nước khung nhiều hơn logic ứng dụng của bạn. Kiểm tra xem hệ thống ống nước 'hoạt động' có thể xảy ra như một phần của quá trình tích hợp hoặc kiểm tra đầu cuối hay không.
Adriaan Koster

4
Tôi ước có một cách để tránh quá nhiều mã viết sẵn.
bluelurker

Tôi nhận được thuộc tính "xmlns" trong một số thẻ như thẻ "liên kết". <link href = "my.css" rel = "stylesheet" type = "text / css" xmlns = " w3.org/1999/xhtml ">. Có cách nào để tránh điều đó không?
ankur_rajput

90

sử dụng một số thứ như

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

//method to convert Document to String
public String getStringFromDocument(Document doc)
{
    try
    {
       DOMSource domSource = new DOMSource(doc);
       StringWriter writer = new StringWriter();
       StreamResult result = new StreamResult(writer);
       TransformerFactory tf = TransformerFactory.newInstance();
       Transformer transformer = tf.newTransformer();
       transformer.transform(domSource, result);
       return writer.toString();
    }
    catch(TransformerException ex)
    {
       ex.printStackTrace();
       return null;
    }
} 

19
@MubasharAhmadtransformer.setOutputProperty(OutputKeys.INDENT, "yes");
Guillaume Polet

10

Điều này đã làm việc cho tôi, như được ghi lại trên trang này :

TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
StringWriter sw = new StringWriter();
trans.transform(new DOMSource(document), new StreamResult(sw));
return sw.toString();

2

Một phiên bản Scala dựa trên câu trả lời của Zaz.

  case class DocumentEx(document: Document) {
    def toXmlString(pretty: Boolean = false):Try[String] = {
      getStringFromDocument(document, pretty)
    }
  }

  implicit def documentToDocumentEx(document: Document):DocumentEx = {
    DocumentEx(document)
  }

  def getStringFromDocument(doc: Document, pretty:Boolean): Try[String] = {
    try
    {
      val domSource= new DOMSource(doc)
      val writer = new StringWriter()
      val result = new StreamResult(writer)
      val tf = TransformerFactory.newInstance()
      val transformer = tf.newTransformer()
      if (pretty)
        transformer.setOutputProperty(OutputKeys.INDENT, "yes")
      transformer.transform(domSource, result)
      Success(writer.toString);
    }
    catch {
      case ex: TransformerException =>
        Failure(ex)
    }
  }

Với điều đó, bạn có thể thực hiện doc.toXmlString()hoặc gọi getStringFromDocument(doc)hàm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.