[英]Java XML parsing using Transformer.transform, works fine on its own, does not work when using Maven
[英]StaX parsing: Transformer.transform method moves cursor automatically, not always nice
我正在使用XMLStreamReader來實現我的目標(拆分xml文件)。 看起來不錯,但仍然無法達到預期效果。 我的目標是從輸入文件中拆分每個節點“ nextTag”:
<?xml version="1.0" encoding="UTF-8"?>
<firstTag>
<nextTag>1</nextTag>
<nextTag>2</nextTag>
</firstTag>
結果應如下所示:
<?xml version="1.0" encoding="UTF-8"?><nextTag>1</nextTag>
<?xml version="1.0" encoding="UTF-8"?><nextTag>2</nextTag>
使用Java引用Split 1GB Xml文件,我通過以下代碼實現了我的目標:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
public class Demo4 {
public static void main(String[] args) throws Exception {
InputStream inputStream = new FileInputStream("input.xml");
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
XMLInputFactory factory = XMLInputFactory.newInstance();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
XMLStreamReader streamReader = factory.createXMLStreamReader(in);
while (streamReader.hasNext()) {
streamReader.next();
if (streamReader.getEventType() == XMLStreamReader.START_ELEMENT
&& "nextTag".equals(streamReader.getLocalName())) {
StringWriter writer = new StringWriter();
t.transform(new StAXSource(streamReader), new StreamResult(
writer));
String output = writer.toString();
System.out.println(output);
}
}
}
}
其實很簡單。 但是,我的輸入文件是單行形式的:
<?xml version="1.0" encoding="UTF-8"?><firstTag><nextTag>1</nextTag><nextTag>2</nextTag></firstTag>
我的Java代碼不再產生所需的輸出,而是僅產生以下結果:
<?xml version="1.0" encoding="UTF-8"?><nextTag>1</nextTag>
花了幾個小時后,我很確定已經找到了原因:
t.transform(new StAXSource(streamReader), new StreamResult(writer));
這是因為在執行了transform方法之后,光標將自動移至下一個事件。 在代碼中,我有以下部分:
while (streamReader.hasNext()) {
streamReader.next();
...
t.transform(new StAXSource(streamReader), new StreamResult(writer));
...
}
第一次轉換后,streamReader直接獲得2次next():
1. from the transform method
2. from the next method in the while loop
因此,在使用這種特定的行XML的情況下,游標永遠無法獲得第二個open標簽。 相反,如果輸入XML具有漂亮的打印形式,則可以從游標到達第二個,因為第一個結束標記后有一個空格事件
不幸的是,我找不到任何設置方法,因此在執行transform方法后,translator不會自動跳至下一個事件。 這真令人沮喪。
有人知道我該如何處理嗎? 從語義上也很受歡迎。 非常感謝。
問候,
拉特納
PS。 我肯定可以寫出解決此問題的方法(在轉換它之前先漂亮地打印xml文檔,但這意味着輸入xml之前已被修改,這是不允許的)
如前所述,如果元素節點彼此直接跟隨,則轉換步驟將繼續執行下一個create元素。
為了解決這個問題,您可以使用嵌套的while循環來重寫代碼,如下所示:
while(reader.next() != XMLStreamConstants.END_DOCUMENT) {
while(reader.getEventType() == XMLStreamConstants.START_ELEMENT && reader.getLocalName().equals("nextTag")) {
StringWriter writer = new StringWriter();
// will transform the current node to a String, moves the cursor to the next START_ELEMENT
t.transform(new StAXSource(reader), new StreamResult(writer));
System.out.println(writer.toString());
}
}
如果您的xml
文件適合存儲在內存中,則可以在JOOX
庫的幫助下進行嘗試,該庫以gradle格式導入:
compile 'org.jooq:joox:1.3.0'
和主類一樣:
import java.io.File;
import java.io.IOException;
import org.joox.JOOX;
import org.joox.Match;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import static org.joox.JOOX.$;
public class Main {
public static void main(String[] args)
throws IOException, SAXException, TransformerException {
DocumentBuilder builder = JOOX.builder();
Document document = builder.parse(new File(args[0]));
Transformer transformer =
TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty("omit-xml-declaration", "no");
final Match $m = $(document);
$m.find("nextTag").forEach(tag -> {
try {
transformer.transform(
new DOMSource(tag),
new StreamResult(System.out));
System.out.println();
}
catch (TransformerException e) {
System.exit(1);
}
});
}
}
它產生:
<?xml version="1.0" encoding="UTF-8"?><nextTag>1</nextTag>
<?xml version="1.0" encoding="UTF-8"?><nextTag>2</nextTag>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.