2015-03-31 63 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空格。