2009-05-15 9 views
7

、私はこのように始まるXMLファイルの一部を変更する:Javaで解析する際に、文書要素の前に空白を入れる方法は?私のアプリケーションで

<?xml version="1.0" encoding="UTF-8"?> 
<!-- $Id: version control yadda-yadda $ --> 

<myElement> 
... 

<myElement>の前に空白行を注意してください。ロード後、変更し、保存し、結果ははるかに楽しいからです:

<?xml version="1.0" encoding="UTF-8"?> 
<!-- $Id: version control yadda-yadda $ --><myElement> 
... 

私はコメントとドキュメントノード間の空白(1改行)は、全てのDOMで表現されていないことが判明しました。次の自己完結型コードは、問題を確実に再現します。

String source = 
    "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n<!-- foo -->\n<empty/>"; 
byte[] sourceBytes = source.getBytes("UTF-16"); 

DocumentBuilder builder = 
    DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
Document doc = 
    builder.parse(new ByteInputStream(sourceBytes, sourceBytes.length)); 

DOMImplementationLS domImplementation = 
    (DOMImplementationLS) doc.getImplementation(); 
LSSerializer lsSerializer = domImplementation.createLSSerializer(); 
System.out.println(lsSerializer.writeToString(doc)); 

// output: <?xml version="1.0" encoding="UTF-16"?>\n<!-- foo --><empty/> 

これを回避する方法を知っている人はいますか?基本的には、出力を入力と同じにします。 (XML宣言はDOMの一部ではないので再生成されますが、ここで問題にはなりません)

+1

" - ><"の最初の出現を探し、2つの改行を追加するカスタムOutputStreamクラスを使用して、これを出力にハッキングしました。最初のドキュメントの子ノードが実際にコメントになっている場合にのみ、このストリームを使用します。まだハックですが、少なくともきちんとカプセル化されています:-) –

+0

私は同じ問題があります。お助けください。 http://stackoverflow.com/questions/30940162/dom-parser-wrong-childnodes-count – user3930361

答えて

2

根本的な原因は、標準DOM Level 3が仕様を壊すことなくドキュメントの子としてテキストノードを表すことができないということです。空白は、準拠しているパーサーによって削除されます。

Document -- 
    Element (maximum of one), 
    ProcessingInstruction, 
    Comment, 
    DocumentType (maximum of one) 

標準に準拠したソリューションが必要で、目的が100%再生ではなく読みやすさが必要な場合は、出力メカニズムで探します。

+0

良い答えですが、これは私の意見では仕様の愚かなバグです。あなたは確かにドキュメント要素の前にテキストを出力することができますが、それを入力することはできません? – Archie

+0

@McDowellこれを避けるために何かできることは、私の質問を見てください。 http://stackoverflow.com/questions/30940162/dom-parser-wrong-childnodes-count – user3930361

1

一般に空白はXMLでは無関係と見なされるため、XMLファイルの解析時には保持されません。 XMLを出力するほとんどのライブラリには、適切な字下げと正しい字下げで出力するオプションがありますが、それは常にかなり一般的です。いいえ "余分な行がありますここに"。

+1

重要な点は、元の入力に*行があったことと、すべての空白ドキュメントの残りの部分で! –

3

なぜこれを避けたいですか?

タグ/要素の外側の空白は、仕様によって重要ではないと定義されています。 DOMが表すinfosetに関する限り、それは単に存在しません。

したがって、DOMを再度シリアル化すると、そこには存在しません。

この空の行に依存するものを開発している場合は...しないでください。

+0

もちろん、この形式に依存するプログラムはありません。 ただし、ファイルには翻訳データが含まれています。彼らはバージョン管理にチェックインされ、継続的に維持されます。したがって、唯一の変更が私のアプリが意図的なものであれば、diffを見るのはいいでしょう。 –

+0

私はそう思っていました...それを扱う唯一の賢明な方法は、ファイル内にこの空の行を開始することではないと思います。私はこの行を保持するための推薦可能な方法はないと思います。たぶん、これらの矛盾を避けるためにチェックインする前に、整頓されたツールを通ってファイルがルールとして渡されるべきであろう。 – Tomalak

+0

@Tomalak ::あなたは私を助けることができます: http://stackoverflow.com/questions/30940162/dom-parser-wrong-childnodes-count – user3930361

6

私は同じ問題を抱えていました。私の解決策は、私自身のXMLパーサーを書くことでした:DecentXML

主な機能:元の入力、空白、エンティティ、すべてを100%保存することができます。詳細については心配しませんが、コードが次のようにXMLを生成する必要がある場合は、

<element 
    attr="some complex value" 
    /> 

とすることができます。

+0

提案ありがとうございました。 DecentXMLは確かに心に留めておくといいですね! * bookmarksIt * "まだ別のパーサー"プロジェクトの少なくとも1つが存在する本当に良い理由があることを知りたい。しかし、私の現在の問題では、処理コード全体に渡って標準のDOM APIを使い、単に出力ステージに行を追加するだけです。 –

+0

次に、ルート要素の前に手動でテキストノードを追加する必要があります。 Documentオブジェクトを見て、ノーマル(非要素)ノードを追加する方法を見てください。それが不可能な場合は、そこに改行をハックするライター/出力ストリーム用のフィルタを作成する必要があります。 –

+0

@AaronDigulla ::これで助けてくれますか?http://stackoverflow.com/questions/30940162/dom-parser-wrong-childnodes-count – user3930361

0

私はKrisとTomalakに同意しますが、空白行はXMLの観点からは関係ありません。アプリケーションで出力に空白行を生成する必要がある場合は、その要件の必要性を確認することをお勧めします。

とにかく、空白行を表示したい場合は、使用しているXMLパーサのソースコードをダウンロードし、その動作を変更することをお勧めします。しかし、これは標準的なXMLではなく、他のアプリケーションと互換性がないことに注意してください。

+1

人によって編集されるXMLファイルはどうですか?その場合、元の書式設定が重要です。 XMLはシリアライゼーションのためだけでなく、バ​​イナリ形式の方がよいでしょう。 – MarioVilas

関連する問題