Java: วิธีการเยื้อง XML ที่สร้างโดย Transformer


112

ฉันใช้ตัวแปลง XML ในตัวของ Java เพื่อรับเอกสาร DOM และพิมพ์ XML ที่เป็นผลลัพธ์ ปัญหาคือไม่มีการเยื้องข้อความเลยทั้งๆที่ตั้งค่าพารามิเตอร์ "เยื้อง" ไว้อย่างชัดเจน

โค้ดตัวอย่าง

public class TestXML {

 public static void main(String args[]) throws Exception {
  ByteArrayOutputStream s;

  Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
  Transformer t = TransformerFactory.newInstance().newTransformer();

  Element a,b;

  a = d.createElement("a");
  b = d.createElement("b");

  a.appendChild(b);

  d.appendChild(a);

  t.setParameter(OutputKeys.INDENT, "yes");

  s = new ByteArrayOutputStream();

  t.transform(new DOMSource(d),new StreamResult(s));

  System.out.println(new String(s.toByteArray()));

 }
}

ผลลัพธ์

<?xml version="1.0" encoding="UTF-8" standalone="no"?><a><b/></a>

ผลลัพธ์ที่ต้องการ

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<a>
 <b/>
</a>

ความคิด?

คำตอบ:


215

คุณต้องเปิดใช้งาน 'INDENT' และกำหนดจำนวนเยื้องสำหรับหม้อแปลง:

t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

อัปเดต:


การอ้างอิง: วิธีการตัดโหนดข้อความเฉพาะช่องว่างจาก DOM ก่อนการทำให้เป็นอนุกรม

(ขอบคุณสมาชิกทุกคนโดยเฉพาะ @ marc-novakowski, @ james-murty และ @saad) :


70
ดูเหมือนจะโง่สำหรับฉันที่การเยื้องเริ่มต้นคือ 0 แต่นอกจากนี้INDENT=yesฉันยังต้องเพิ่มสิ่งนี้ด้วย:t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
lapo

1
ระวัง. คุณสมบัติการเยื้องนี้ใช้ไม่ได้ใน java 5 มันทำใน java 7 ยังไม่ได้ลองใน java 6
Hilikus

4
หากมีโหนดภายในที่มีหลายบรรทัดคุณสามารถเยื้องส่วนด้านในด้วยได้หรือไม่? เพียงใช้สิ่งนี้ไม่ได้เยื้องโหนดด้านใน
eipark

1
@eipark กับstackoverflow.com/a/979606/837530ฉันลบช่องว่างและตอนนี้เยื้องเหมือนมีเสน่ห์
Sa'ad

1
@lapo หากผู้ให้บริการของคุณเป็น xalan (ซึ่งอาจเป็นไปได้หากใช้งานได้) จะมีให้ในorg.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT
OrangeDog

21

วิธีแก้ปัญหาที่แนะนำไม่ได้ผลสำหรับฉัน ดังนั้นฉันจึงยังคงค้นหาทางเลือกอื่นซึ่งลงเอยด้วยการผสมผสานระหว่างสองอย่างก่อนที่จะกล่าวถึงและขั้นตอนที่สาม

  1. ตั้งค่าการเยื้องหมายเลขลงในโรงงานหม้อแปลง
  2. เปิดใช้งานการเยื้องในหม้อแปลง
  3. ห่อ otuputstream ด้วยนักเขียน (หรือนักเขียนบัฟเฟอร์)
//(1)
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));

//(2)
Transformer t = tf.newTransformer();
t.setOutputProperty(OutputKeys.INDENT, "yes");

//(3)
t.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "utf-8"));

คุณต้องทำ (3) เพื่อแก้ปัญหาพฤติกรรม "บั๊ก" ของโค้ดการจัดการ xml

ที่มา: johnnymac75 @ http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446

(หากฉันอ้างแหล่งที่มาไม่ถูกต้องโปรดแจ้งให้เราทราบ)


3
"out" ในบรรทัดสุดท้ายหมายถึงอะไร?
mujimu

คุณต้องสร้างจำนวนเต็มใหม่โดยใช้ตัวสร้างหรือไม่?
Benjineer

ฉันเดาว่าเพราะผู้ให้บริการของคุณไม่ใช่ Xalan คุณสามารถตรวจสอบสิ่งที่คุณTransformerFactoryเป็นจริงเพื่อให้คนอื่นรู้
OrangeDog

ขั้นตอนที่ 3 โดยใช้ a Writerเป็นเอาต์พุตเป็นสิ่งสำคัญ
erickson

14

รหัสต่อไปนี้ใช้งานได้สำหรับฉันกับ Java 7 ฉันตั้งค่าการเยื้อง (ใช่) และจำนวนการเยื้อง (2) บนหม้อแปลง (ไม่ใช่โรงงานหม้อแปลง) เพื่อให้ทำงานได้

TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.transform(source, result);

วิธีแก้ปัญหาของ @ mabac ในการตั้งค่าแอตทริบิวต์ไม่ได้ผลสำหรับฉัน แต่ความคิดเห็นของ @ lapo พิสูจน์แล้วว่ามีประโยชน์


8

นำเข้า com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory

transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "2");

นี่เป็นคลาสภายในดังนั้นโค้ดของคุณจะไม่พกพาไปยัง JVM อื่น ๆ (หรือใหม่กว่า)
OrangeDog

5

หากคุณต้องการเยื้องคุณต้องระบุในไฟล์TransformerFactory.

TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));
Transformer t = tf.newTransformer();

4

ฉันใช้ไลบรารี Xerces (Apache) แทนที่จะยุ่งกับ Transformer เมื่อคุณเพิ่มไลบรารีแล้วให้เพิ่มโค้ดด้านล่าง

OutputFormat format = new OutputFormat(document);
format.setLineWidth(65);
format.setIndenting(true);
format.setIndent(2);
Writer outxml = new FileWriter(new File("out.xml"));
XMLSerializer serializer = new XMLSerializer(outxml, format);
serializer.serialize(document);

ใช่. ฉันลองใช้วิธีอื่น ๆ ทั้งหมดกับ Transformer แต่ก็พังทั้งหมด ห้องสมุด W3C ทั้งหมดเป็นระเบียบ Xerces ทำงานได้
Tuntable

3

สำหรับฉันเพิ่มDOCTYPE_PUBLICงาน:

transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "10");

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