web-dev-qa-db-ja.com

Java:Transformerで生成されたXMLをインデントする方法

Javaの組み込みXMLトランスフォーマーを使用して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>

考え?

105
Mike

「INDENT」を有効にし、トランスフォーマーのインデント量を設定する必要があります。

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

更新:


参照: シリアル化の前にDOMから空白のみのテキストノードを削除する方法?

(特に@ marc-novakowski、@ james-murty、@ saadのすべてのメンバーに感謝します)

208
adatapost

提案された解決策のどちらも私にはうまくいきませんでした。そこで、私は代替ソリューションを探し続けました。それは、前述の2つと3番目のステップの混合物になりました。

  1. インデント番号をtransformerfactoryに設定します
  2. トランスフォーマーのインデントを有効にします
  3. otuputstreamをライター(またはbufferedwriter)でラップします
//(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

(ソースを間違って引用した場合はお知らせください)

19
mabac

次のコードはJava 7。

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のコメントは役に立ちました。

14
remipod

import com.Sun.org.Apache.xml.internal.serializer.OutputPropertiesFactory

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

Transformerをいじるのではなく、Xerces(Apache)ライブラリを使用しました。ライブラリを追加したら、以下のコードを追加します。

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);
4
sevensevens

インデントが必要な場合は、TransformerFactoryに指定する必要があります。

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

私にとってDOCTYPE_PUBLICを追加するとうまくいきました:

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