2016-11-20 2 views
1

私は、STAXイベントモデルを使用して、XMLファイル内のテキストエンティティを変更するユーティリティを作成しています。私は、ソース文書の空白の一部が出力にコピーされていないことがわかりました。私は、このサンプル・プログラムを書いた:オラクルのJava 7に付属しているデフォルトスタックスの実装を使用して空白をスキップするStaxイベントリーダー

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.nio.charset.StandardCharsets; 

import javax.xml.stream.*; 
import javax.xml.stream.events.*; 

public class EventCopy { 
    private static final String INPUT = 
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
      "<foo><bar>baz</bar></foo>\n"; 

    public static void main(String[] args) throws XMLStreamException, IOException { 
     InputStream reader = new ByteArrayInputStream(INPUT.getBytes(StandardCharsets.UTF_8)); 
     OutputStream writer = new ByteArrayOutputStream(); 

     XMLInputFactory input = XMLInputFactory.newInstance(); 
     XMLEventReader xmlReader = input.createXMLEventReader(reader, "UTF-8"); 
     try { 
      XMLOutputFactory output = XMLOutputFactory.newInstance(); 
      XMLEventWriter xmlWriter = output.createXMLEventWriter(writer, "UTF-8"); 
      try { 
       while (xmlReader.hasNext()) { 
        XMLEvent event = xmlReader.nextEvent(); 
        System.out.print(event.getEventType() + ","); 
        xmlWriter.add(event); 
       } 
      } finally { 
       xmlWriter.close(); 
      } 
     } finally { 
      xmlReader.close(); 
     } 
     System.out.println("\n[" + writer.toString() + "]"); 
    } 
} 

を、この出力:

7,1,1,4,2,2,8, 
[<?xml version="1.0" encoding="UTF-8"?><foo><bar>baz</bar></foo>] 

XMLプロローグと入力の終わりを以下の改行が消えてしまいました。読者はイベントを生成しないようだ。

私は多分XMLリーダーは最後のXMLタグの端部に位置する入力ストリームを残していたことを考えて、入力から出力まで末尾の文字をコピーするコードを追加してみました:

... 
    } finally { 
     xmlReader.close(); 
    } 
    int ii; 
    while (-1 != (ii = reader.read())) { 
     writer.write(ii); 
    } 

しかし、この何の効果もありません。

STAXにこのXMLをより忠実にコピーさせる方法はありますか?別のSTAX実装がここでは異なる動作をしますか?

+0

"\ n"の代わりに "
"を使用してみてください –

答えて

0

リファレンス:XML spec

整形式XML文書が指定文法に従う:

[1] document ::= prolog element Misc* 
[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? 
[23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' 
[27] Misc  ::= Comment | PI | S 
[3] S  ::= (#x20 | #x9 | #xD | #xA)+ 

[39] element ::= EmptyElemTag 
        | STag content ETag 
[40] STag  ::= '<' Name (S Attribute)* S? '>' 
[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* 
[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) 
[42] ETag  ::= '</' Name S? '>' 

XMLDeclとルート要素との間の改行、およびルート要素次々にパーサーがそれ自体を無視することを許可しているのはちょうどSです。

異なる空白の例を挙げておきます。あなたがわずかに異なるXMLがあるとします。

private static final String INPUT = 
     "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
     "<foo>\n<bar>baz</bar></foo>\n"; 

<foo><bar>の間に改行がCharDataです。 StAXはこの文字のイベントを正しく生成することに注意してください。

実際にSを保存したい場合は、XML文書ではなくテキストとしてINPUTを読む必要があります。 2つのXML文書インスタンス(これらの2つの特定のS文字を含むものとそれ以外のもの)は同等です。

+0

私は出力が入力と意味的に同等であると考えました。それは私が探しているものではありません。私は、このXMLフィルターがXMLに不必要な変更を加えた場合、私のユーザーが不平を言うのではないかと心配しています。私は、変更が問題ではないと主張する必要がある立場にはいません。 – Kenster

+0

@Kensterあなたはオプションが足りないと思います。次にXMLをテキストとして読み込みます。私はほとんどのXMLパーサーがそれらの空白を無視すると信じています – nandsito

関連する問題