2010-12-04 135 views
4

XML看起來像這樣:STAX - 獲取XML節點串

<statements> 
    <statement account="123"> 
     ...stuff... 
    </statement> 
    <statement account="456"> 
     ...stuff... 
    </statement> 
</statements> 

我使用STAX來處理一個「<statement>」的時間和我得到的工作。我需要將整個語句節點作爲一個字符串,以便我可以創建「123.xml」和「456.xml」,或者甚至可以將它加載到按帳戶索引的數據庫表中。使用

這種方法:http://www.devx.com/Java/Article/30298/1954

我希望做這樣的事情:

String statementXml = staxXmlReader.getNodeByName("statement"); 

//load statementXml into database 
+1

準確地說你的問題是什麼? – javamonkey79 2010-12-04 04:58:47

回答

1

爲什麼不直接使用XPath這個?

你可以有一個相當簡單的xpath來獲取所有'語句'節點。

像這樣:

//statement 

編輯#1:如果可能的話,看看dom4j。你可以讀取字符串並相當簡單地獲取所有'語句'節點。

編輯#2:使用dom4j的,這是你會怎麼做: (從他們的食譜)

String text = "your xml here"; 
Document document = DocumentHelper.parseText(text); 

public void bar(Document document) { 
    List list = document.selectNodes("//statement"); 
    // loop through node data 
} 
+0

JDK/JRE中還存在標準XPath庫:http://stackoverflow.com/questions/3939636/how-to-use-xpath-on-xml-docs-having-default-namespace/3941277#3941277 – 2010-12-06 14:24:43

+2

海報明確提到了StAX,所以我不認爲dom4j或其他庫的指針確實對他有很大幫助...... – t0r0X 2012-07-25 07:30:32

+1

鑑於OP從未問過任何問題,所以使用xPath的建議與其他任何方法一樣。可能更好。 – 2012-08-24 13:17:44

0

我一直在使用Google,這似乎痛苦艱難。

給我的XML,我認爲它可能只是簡單:

StringBuilder buffer = new StringBuilder(); 
for each line in file { 
    buffer.append(line) 
    if(line.equals(STMT_END_TAG)){ 
     parse(buffer.toString()) 
     buffer.delete(0,buffer.length) 
    } 
} 

private void parse(String statement){ 
    //saxParser.parse(new InputSource(new StringReader(xmlText)); 
    // do stuff 
    // save string 
} 
2

斯塔克斯是一個低級別的訪問API,它不具有任何查找或方法遞歸訪問內容。但是你究竟想要做什麼?你爲什麼要考慮Stax?除了使用適用於XPath的樹模型(DOM,XOM,JDOM,Dom4j)之外,處理數據時的最佳選擇通常是像JAXB這樣的數據綁定庫。有了它,您可以傳遞Stax或SAX reader,並要求它將xml數據綁定到Java bean中,而不是搞亂xml過程Java對象。這通常更方便,而且通常表現很好。 只有大文件的訣竅是,你不希望一次綁定整個事物,而是綁定每個子樹(在你的情況下,一次一個'語句')。 這是通過迭代Stax XmlStreamReader,然後使用JAXB進行綁定來完成的。

5

您可以爲此使用StAX。您只需將XMLStreamReader提前到語句的開始元素即可。檢查帳戶屬性以獲取文件名。然後使用javax.xml.transform API將StAXSource轉換爲包裝文件的StreamResult。這將推進XMLStreamReader,然後重複此過程。

import java.io.File; 
import java.io.FileReader; 
import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLStreamConstants; 
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 Demo { 

    public static void main(String[] args) throws Exception { 
     XMLInputFactory xif = XMLInputFactory.newInstance(); 
     XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml")); 
     xsr.nextTag(); // Advance to statements element 

     while(xsr.nextTag() == XMLStreamConstants.START_ELEMENT) { 
      TransformerFactory tf = TransformerFactory.newInstance(); 
      Transformer t = tf.newTransformer(); 
      File file = new File("out" + xsr.getAttributeValue(null, "account") + ".xml"); 
      t.transform(new StAXSource(xsr), new StreamResult(file)); 
     } 
    } 

} 
5

我有一個類似的任務,雖然原來的問題比一年還舊,但我找不到滿意的答案。到目前爲止,最有趣的答案是Blaise Doughan的答案,但是我無法讓它在我期望的XML上運行(也許一些底層解析器的參數可能會改變它?)。在這裏,XML,非常simplyfied:

<many-many-tags> 
    <description> 
     ... 
     <p>Lorem ipsum...</p> 
     Devils inside... 
     ... 
    </description> 
</many-many-tags> 

我的解決辦法:

public static String readElementBody(XMLEventReader eventReader) 
    throws XMLStreamException { 
    StringWriter buf = new StringWriter(1024); 

    int depth = 0; 
    while (eventReader.hasNext()) { 
     // peek event 
     XMLEvent xmlEvent = eventReader.peek(); 

     if (xmlEvent.isStartElement()) { 
      ++depth; 
     } 
     else if (xmlEvent.isEndElement()) { 
      --depth; 

      // reached END_ELEMENT tag? 
      // break loop, leave event in stream 
      if (depth < 0) 
       break; 
     } 

     // consume event 
     xmlEvent = eventReader.nextEvent(); 

     // print out event 
     xmlEvent.writeAsEncodedUnicode(buf); 
    } 

    return buf.getBuffer().toString(); 
} 

用例:

XMLEventReader eventReader = ...; 
while (eventReader.hasNext()) { 
    XMLEvent xmlEvent = eventReader.nextEvent(); 
    if (xmlEvent.isStartElement()) { 
     StartElement elem = xmlEvent.asStartElement(); 
     String name = elem.getName().getLocalPart(); 

     if ("DESCRIPTION".equals(name)) { 
      String xmlFragment = readElementBody(eventReader); 
      // do something with it... 
      System.out.println("'" + fragment + "'"); 
     } 
    } 
    else if (xmlEvent.isEndElement()) { 
     // ... 
    } 
} 

注意,提取XML片段將包含完整的提取正文內容,包括白色空間和評論。根據需要過濾這些內容,或者使緩衝區大小可以參數化,但爲了簡化代碼,已將其忽略:

' 
    <description> 
     ... 
     <p>Lorem ipsum...</p> 
     Devils inside... 
     ... 
    </description> 
    '