2015-03-31 34 views
0

我正在使用SAX(Simple API for XML)解析XML文檔。我得到了文件所有標籤的輸出,但我希望它能在父子層次結構中顯示標籤。 例如: 這是我的輸出在Sax XML解析器中獲取父子層次

<dblp> 
<www> 
<author> 
</author><title> 
</title><url> 
</url><year> 
</year></www><inproceedings> 
<month> 
</month><pages> 
</pages><booktitle> 
</booktitle><note> 
</note><cdrom> 
</cdrom></inproceedings><article> 
<journal> 
</journal><volume> 
</volume></article><ee> 
</ee><book> 
<publisher> 
</publisher><isbn> 
</isbn></book><incollection> 
<crossref> 
</crossref></incollection><editor> 
</editor><series> 
</series></dblp> 

但我想它來顯示這樣的輸出(它顯示額外間距孩子(這就是我希望它是))

<dblp> 
    <www> 
    <author> 
    </author> 
    <title> 
    </title> 
    <url> 
    </url> 
    <year> 
    </year> 
    </www> 
    <inproceedings> 
    <month> 
    </month> 
    <pages> 
    </pages> 
    <booktitle> 
    </booktitle> 
    <note> 
    </note> 
    <cdrom> 
    </cdrom> 
    </inproceedings> 
    <article> 
    <journal> 
    </journal> 
    <volume> 
    </volume> 
    </article> 
    <ee> 
    </ee> 
    <book> 
    <publisher> 
    </publisher> 
    <isbn> 
    </isbn> 
    </book> 
    <incollection> 
    <crossref> 
    </crossref> 
    </incollection> 
    <editor> 
    </editor> 
    <series> 
    </series> 
</dblp> 

但我無法弄清楚如何檢測解析器是解析父標籤還是孩子。

這裏是我的代碼:

package com.teamincredibles.sax; 

import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 

import org.xml.sax.Attributes; 
import org.xml.sax.SAXException; 
import org.xml.sax.helpers.DefaultHandler; 

public class Parser extends DefaultHandler { 

    public void getXml() { 
    try { 
     SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); 
     SAXParser saxParser = saxParserFactory.newSAXParser(); 
     final MySet openingTagList = new MySet(); 
     final MySet closingTagList = new MySet(); 
     DefaultHandler defaultHandler = new DefaultHandler() { 

     public void startDocument() throws SAXException { 
      System.out.println("Starting Parsing...\n"); 
     } 

     public void endDocument() throws SAXException { 
      System.out.print("\n\nDone Parsing!"); 
     } 

     public void startElement(String uri, String localName, String qName, 
      Attributes attributes) throws SAXException { 
      if (!openingTagList.contains(qName)) { 
      openingTagList.add(qName); 
      System.out.print("<" + qName + ">\n"); 
      } 
     } 

     public void characters(char ch[], int start, int length) 
     throws SAXException { 
      /*for(int i=start; i<(start+length);i++){ 
      System.out.print(ch[i]); 
     }*/ 
     } 

     public void endElement(String uri, String localName, String qName) 
     throws SAXException { 
      if (!closingTagList.contains(qName)) { 
      closingTagList.add(qName); 
      System.out.print("</" + qName + ">"); 
      } 
     } 
     }; 

     saxParser.parse("xml/sample.xml", defaultHandler); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 

    public static void main(String args[]) { 
    Parser readXml = new Parser(); 
    readXml.getXml(); 
    } 
} 
+0

嗨。你可以添加你的sample.xml嗎? – 2015-04-02 20:04:24

+0

是的,我可以加上 – 2015-04-02 20:04:46

回答

1

,可以考慮一個StAX的實現:

package be.duo.stax; 

import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLStreamConstants; 
import javax.xml.stream.XMLStreamException; 
import javax.xml.stream.XMLStreamReader; 

public class StaxExample { 

    public void getXml() { 
     InputStream is = null; 
     try { 
      is = new FileInputStream("c:\\dev\\sample.xml"); 

      XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
      XMLStreamReader reader = inputFactory.createXMLStreamReader(is); 

      parse(reader, 0); 

     } catch(Exception ex) { 
      System.out.println(ex.getMessage()); 
     } finally { 
      if(is != null) { 
       try { 
        is.close(); 
       } catch(IOException ioe) { 
        System.out.println(ioe.getMessage()); 
       } 
      } 
     } 

    } 

    private void parse(XMLStreamReader reader, int depth) throws XMLStreamException { 
     while(true) { 
      if(reader.hasNext()) { 
       switch(reader.next()) { 
       case XMLStreamConstants.START_ELEMENT: 
        writeBeginTag(reader.getLocalName(), depth); 
        parse(reader, depth+1); 
        break; 
       case XMLStreamConstants.END_ELEMENT: 
        writeEndTag(reader.getLocalName(), depth-1); 
        return; 
       } 
      } 
     } 
    } 

    private void writeBeginTag(String tag, int depth) { 
     for(int i = 0; i < depth; i++) { 
      System.out.print(" "); 
     } 
     System.out.println("<" + tag + ">"); 
    } 

    private void writeEndTag(String tag, int depth) { 
     for(int i = 0; i < depth; i++) { 
      System.out.print(" "); 
     } 
     System.out.println("</" + tag + ">"); 
    } 

    public static void main(String[] args) { 
     StaxExample app = new StaxExample(); 
     app.getXml(); 
    } 

} 

沒有爲StAX的一個成語,像這樣的循環在XML中的每個標籤:

private MyTagObject parseMyTag(XMLStreamReader reader, String myTag) throws XMLStreamException { 
    MyTagObject myTagObject = new MyTagObject(); 
    while (true) { 
     switch (reader.next()) { 
     case XMLStreamConstants.START_ELEMENT: 
      String localName = reader.getLocalName(); 
      if(localName.equals("myOtherTag1")) { 
       myTagObject.setMyOtherTag1(parseMyOtherTag1(reader, localName)); 
      } else if(localName.equals("myOtherTag2")) { 
       myTagObject.setMyOtherTag2(parseMyOtherTag2(reader, localName)); 
      } 
      // and so on 
      break; 
     case XMLStreamConstants.END_ELEMENT: 
      if(reader.getLocalName().equals(myTag) { 
       return myTagObject; 
      } 
      break; 
    } 
} 
+0

謝謝@Stefaan – 2015-04-02 22:08:47

+1

請在選擇使用StAX時多閱讀一下。您可以過濾元素以使其更快。另外,Java 7/8可以打開字符串,這使得它更快,否則,如果... – 2015-04-02 22:13:20

+0

肯定先生,你現在已經對我感興趣了。謝謝你。 – 2015-04-02 22:15:20

0

以及你嘗試過什麼?你應該使用在這裏發現了一個變壓器:How to pretty print XML from Java?

Transformer transformer = TransformerFactory.newInstance().newTransformer(); 
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
//initialize StreamResult with File object to save to file 
StreamResult result = new StreamResult(new StringWriter()); 
DOMSource source = new DOMSource(doc); 
transformer.transform(source, result); 
String xmlString = result.getWriter().toString(); 
System.out.println(xmlString); 
0

幾乎任何有用的SAX應用程序需要保持一個堆棧。當調用startElement時,將信息推送到堆棧,當調用endElement時,彈出堆棧。您放入堆棧的具體內容取決於應用程序;它通常是元素名稱。對於你的應用程序,你實際上並不需要一個完整的堆棧,你只需要知道它的深度。您可以通過在startElement中使用depth++並在endElement()中使用depth--來解決此問題。然後在元素名稱前輸出depth空格。