How to Parse unknown XML structure using STAX Event Driven Or Stream API
我尝试使用dom解析未知的XML结构并获得成功,但现在我尝试使用stax事件或流解析器,因为XML文件很大。虽然我使用sax进行此操作并获得成功。但现在我对stax有点好奇。现在我真的想了解它。
我对此做了一些研究并编写了这个代码
这是Stax流媒体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public static void main(String args[]) throws XMLStreamException, FileNotFoundException { XMLInputFactory xf = XMLInputFactory.newInstance(); XMLStreamReader xsr = xf.createXMLStreamReader(new InputStreamReader(new FileInputStream("c:\\file.xml"))); XMLInputFactoryImpl x = new XMLInputFactoryImpl(); while (xsr.hasNext()) { int e = xsr.next(); if (e == XMLStreamConstants.START_ELEMENT) { System.out.println("Element Start Name:" + xsr.getLocalName()); } if (e == XMLStreamReader.END_ELEMENT) { System.out.println("Element End Name:" + xsr.getLocalName()); } if (e == XMLStreamConstants.CHARACTERS) { System.out.println("Element Text:" + xsr.getText()); } } } |
和Stax事件驱动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public static void main(String[] args) throws XMLStreamException, FileNotFoundException { // TODO code application logic here // TODO Auto-generated method stub XMLInputFactory xif = XMLInputFactory.newInstance(); XMLEventReader xer = xif.createXMLEventReader(new InputStreamReader(new FileInputStream("c:\\file.xml"))); while (xer.hasNext()) { XMLEvent e = xer.nextEvent(); if (e.isCharacters()) { System.out.println("Element Text :"+e.asCharacters().getData()); } if (e.isStartElement()) { System.out.println("Start Element :"+e.asStartElement().getName()); } if (e.isEndElement()) { System.out.println("End Element :"+e.asEndElement().getName()); } } } } |
在上述两个代码中,父节点还打印空白文本,但不应该因为XML子节点只包含文本,而只应打印子节点文本。例如
1 2 3 4 5 6 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> <student id="1"> <fname>TestFirstName</fname> <lname>TestLastName</lname> <sectionname rollno="1">A</sectionname> </student> |
它应该打印testFirstName、testLastname等,这意味着如果父节点要打印字符(e==xmlstreamConstants.characters),或者如果父节点要打印字符(e.isCharacters()),它不应该返回true。因此,我如何修改我的代码来解析XML文件的任何级别,它可能在任何深度或任何层叠级别上。
这是我使用Stax流的解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public static void main(String[] args) throws FileNotFoundException, XMLStreamException { XMLInputFactory xf=XMLInputFactory.newInstance(); XMLStreamReader xsr=xf.createXMLStreamReader(new InputStreamReader(new FileInputStream("c:\\test.xml"))); String startElement = null; String endElement =null; String elementTxt = null; while (xsr.hasNext()) { int e = xsr.next(); if(e==XMLStreamConstants.START_ELEMENT){ //System.out.println("StartElement Name :" + xsr.getLocalName()); startElement = xsr.getLocalName(); } if(e==XMLStreamConstants.END_ELEMENT){ //System.out.println("EndElement Name :" + xsr.getLocalName()); endElement = xsr.getLocalName(); if(startElement.equalsIgnoreCase(endElement)) System.out.println(" ElementName :"+ startElement +" ElementText :" + elementTxt); } if(e==XMLStreamConstants.CHARACTERS){ //System.out.println("Element TextValue :" + xsr.getText()); elementTxt = (xsr.getText().contains(" ")) ?"" : xsr.getText(); } } } |
这是我使用Stax事件的解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public static void main(String[] args) throws XMLStreamException,FileNotFoundException { // TODO code application logic here // TODO Auto-generated method stub XMLInputFactory xif = XMLInputFactory.newInstance(); XMLEventReader xer = xif.createXMLEventReader(new InputStreamReader(new FileInputStream("c:\\test.xml"))); String startElement = null; String endElement = null; String elementTxt = null; while (xer.hasNext()) { XMLEvent e = xer.nextEvent(); if (e.isCharacters()) { elementTxt = (e.asCharacters().getData().contains(" ")) ?"": e.asCharacters().getData(); } if (e.isStartElement()) { // System.out.println("Start Element :"+e.asStartElement().getName()); startElement = e.asStartElement().getName().toString(); } if (e.isEndElement()) { // System.out.println("End Element :"+e.asEndElement().getName()); endElement = e.asEndElement().getName().toString(); if (startElement.equalsIgnoreCase(endElement)) System.out.println(" ElementName :" + startElement +" ElementText :" + elementTxt); } } } |
事件分析序列是正确的,您有对空字符的调用,因为有漂亮的打印格式(空格或制表符)。如果您的XML是线性(平面)的,那么您将不会有这些额外的事件。
从stax文档中,您可以看到"可忽略的空白和重要的空白也被报告为字符事件。":您只需要去掉空白。这样可以添加测试
1 2 3 4 | XMLEvent e = xer.nextEvent(); if (e.isCharacters() && !e.asCharacters().isWhiteSpace()) { System.out.println("Element Text :"+e.asCharacters().getData()); } |
这应该过滤掉空白空间,只有你预期的事件。