2016-11-20 69 views
1

我正在編寫一個實用程序來使用STAX事件模型來更改XML文件中的文本實體。我發現源文檔中的一些空白區域沒有被複制到輸出中。我寫了這個示例程序: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() + "]"); 
    } 
} 

使用帶有甲骨文的Java 7的默認斯塔克斯實現,該電源輸出:

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

A-良好的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,那麼您需要將文本替換爲INPUT而不是XML文檔。請注意,兩個XML文檔實例,其中一個具有這兩個特定的S字符,另一個沒有它們,它們是等效的。

+0

我認爲輸出在語義上等同於輸入。那不是我正在尋找的東西。我擔心如果這個XML過濾器對XML進行了不必要的更改,那麼我的用戶會抱怨,並且我不希望與他們爭辯說這些更改無關緊要。 – Kenster

+0

@Kenster我猜你缺乏選擇。然後將XML讀爲文本。我相信大多數XML解析器都會忽略這些空格 – nandsito