2011-01-06 25 views
27

実際には、javax.xml.stream.XMLStreamWriter(Java SE 6)を使用して書式設定されたXMLを直接書き込む方法はありませんか? JAXBやDOMライブラリなどの他のXML APIがこれを行うことができるので、これは本当に信じられません。 .NET XMLStreamWriterでさえ、このAFAIKに相当します(クラスがSystem.Xml.XmlTextWriterであることを正しく覚えていれば)。XMLStreamWriter:インデント

これは、書式化された出力を生成するためにXMLを再解析することだけです。

例えば:

  StringWriter sw = new StringWriter(); 
    XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory(); 
    XMLStreamWriter xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(sw); 
    writeXml(xmlStreamWriter); 
    xmlStreamWriter.flush(); 
    xmlStreamWriter.close(); 

    TransformerFactory factory = TransformerFactory.newInstance(); 

    Transformer transformer = factory.newTransformer(); 
    transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); 

    StringWriter formattedStringWriter = new StringWriter(); 
    transformer.transform(new StreamSource(new StringReader(sw.toString())), new StreamResult(formattedStringWriter)); 
    System.out.println(formattedStringWriter); 

この解決策に伴う問題は、プロパティ "{http://xml.apache.org/xslt}indent-amount" です。私はそれに関するドキュメンテーションを見つけられず、ポータブルであることが保証されていないようです。

標準Java 6クラスでこれを行うには、他にどのようなオプションがありますか? JAXBまたはDOMオブジェクトグラフを作成して、かなり印刷しますか?

答えて

6

writeXmlメソッドで文書の書式設定に必要なコードを追加できます。深度カウンターを単に維持するだけです(入れ子のレベルを示すため)。その後、WriteStandElementを書き込む前に、writeEndElementの後に深さインデックスを使用してインデントを挿入します。

for(int x=0; x<depth; x++) { 
    xmlStreamWriter.writeCharacters(" "); 
} 
+0

このようなwriteTextメソッドは見つかりませんでしたか? http://download.oracle.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriterhtml – Puce

+0

うーん、おそらくwriteCharactersを使っていたかもしれませんが、私はこれを要素の内容のためだけに考えました... – Puce

+0

あなたは正しいはずですが、writeCharactersだったはずです。このメソッドは、単一要素内だけでなく、ドキュメント内のどこにでもテキストを挿入するために使用できます。 –

1

あなたは標準java.xmlインタフェースが基本となる実装(ApacheのXercesのは)ないにも関わらず、直列化を制御なしに少しを提供することを正しいです。私はこの問題を解決しなければなりませんでした。私が思いついたのは、Xercesのコピーを入れて、org.apache.xml.serializeクラスを使用することでした。

+1

はい、私はそのような解決策について読んだことがありますが、Xerces 2.9.0以降、このパッケージは非推奨になりました。http://xerces.apache.org/xerces2-j/javadocs/other/org/apache/xml/serialize/package -summary.html – Puce

34

この正確なquestionは、いくつかのヶ月前に回答されているとone of the answersがIndentingXMLStreamWriterクラスを使用することです:

XMLOutputFactory xmlof = XMLOutputFactory.newInstance(); 
XMLStreamWriter writer = new IndentingXMLStreamWriter(xmlof.createXMLStreamWriter(out)); 

それは限りコードが行くようにきちんとした解決策ですが、慎重に:これははcom.sunです春のバッチとその一般的な可用性の保証はありません。*クラス、...

+1

申し訳ありませんが、これは公開APIではありません。 – Puce

+1

'IndentingXMLStreamWriter'クラスとその基底クラス' DelegatingXMLStreamWriter'は、逆コンパイラで開くことができます(IntelliJ IDEAには現在組み込まれています)、独自のプロジェクトの一部としてソース形式で保存されます。だから、彼らの「未発表」は本当に問題ではありません。これを行う場合は、sunのコードのバグを修正してください: 'onEmptyElement()'メソッドで 'writeCharacters(" \ n ");'の呼び出しは 'super.writeCharacters(" \ n ");代わりに。 –

2

が、これはこのJIRA BATCH-1867

public class IndentingStaxEventItemWriter<T> extends StaxEventItemWriter<T> { 

    @Setter 
    @Getter 
    private boolean indenting = true; 

    @Override 
    protected XMLEventWriter createXmlEventWriter(XMLOutputFactory outputFactory, Writer writer) throws XMLStreamException { 
    if (isIndenting()) { 
     return new IndentingXMLEventWriter(super.createXmlEventWriter(outputFactory, writer)); 
    } 
    else { 
     return super.createXmlEventWriter(outputFactory, writer); 
    } 
    } 

} 
以来のサブクラスが必要です

しかし、これは春のバッチは、StAXの出力インデントするコードが含まれていないためadditionnal依存関係が必要です。念のため

<dependency> 
    <groupId>net.java.dev.stax-utils</groupId> 
    <artifactId>stax-utils</artifactId> 
    <version>20070216</version> 
</dependency> 
+1

興味深いのは、IndentingXMLEventWriterを提供するstax-utilsライブラリで、Spring Batchから独立しているようです。ヒントありがとう! – Puce

2

を、サクソンはあなたがs9apiインタフェースを介してシリアライズてXMLStreamWriterを取得することができます:

Processor p = new Processor(); 
Serializer s = p.newSerializer(); 
s.setOutputProperty(Property.INDENT, "yes"); 
XMLStreamWriter w = s.getXMLStreamWriter(); 

シリアライザは、すべてのXSLT定義の出力プロパティ(「インデント」を含む)といくつかのSaxon固有のプロパティを公開します。

+0

もう少し完全なバージョンです: http://stackoverflow.com/questions/10105187/java-indentingxmlstreamwriter-alternative/30637501#30637501 –

2

私は"{http://xml.apache.org/xslt}indent-amount"プロパティを考慮して答えはありません。しかし、すべての出力を再解析する必要なく、トランスポータを移植することができます。下のコードのようなものを使って、かわいいプリントXMLStreamWriterを作成することができます。

public static void main(String[] args) { 
    XMLStreamWriter xmlStreamWriter = createXMLStreamWriter(new OutputStreamWriter(System.out)); 
    writeXml(xmlStreamWriter); 
} 

private static XMLStreamWriter createXMLStreamWriter(Writer textWriter) throws XMLStreamException { 
    SAXTransformerFactory xmlTransformerFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); 
    TransformerHandler transformingSAXHandler; 
    try { 
     transformingSAXHandler = xmlTransformerFactory.newTransformerHandler(); 
    } catch (TransformerConfigurationException e) { 
     throw new XMLStreamException(e); 
    } 
    Transformer xmlTransformer = transformingSAXHandler.getTransformer(); 
    xmlTransformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
    transformingSAXHandler.setResult(new StreamResult(textWriter)); 

    XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance(); 
    return xmlOutputFactory.createXMLStreamWriter(new SAXResult(transformingSAXHandler)); 
} 
+0

最後の行でこれが発生します: 'java.lang.UnsupportedOperationException:型javax.xmlの結果.transform.sax.SAXResult @ 184f6be2はサポートされていません。サポートされる結果のタイプは、DOMResult、StAXResult、およびStreamResult'です。 Javaバージョン1.8u74を使用していますか? – sjngm

+0

基本的な実装がApache Xercesの場合はうまくいくはずですが、他の実装では動作することは保証されていません... –