Search code examples
javaxmlxml-parsingstax

How to get element only elements with values Stax


I'm trying to get only elements that have text, ex xml :

<root>
      <Item>
        <ItemID>4504216603</ItemID>
        <ListingDetails>
          <StartTime>10:00:10.000Z</StartTime>
          <EndTime>10:00:30.000Z</EndTime>
          <ViewItemURL>http://url</ViewItemURL>
            ....
           </item> 

It should print

Element Local Name:ItemID
Text:4504216603
Element Local Name:StartTime
Text:10:00:10.000Z
Element Local Name:EndTime
Text:10:00:30.000Z
Element Local Name:ViewItemURL
Text:http://url

This code prints also root, item etc. Is it even possible, it must be I just can't google it.

XMLInputFactory inputFactory = XMLInputFactory.newInstance();
InputStream input = new FileInputStream(new File("src/main/resources/file.xml"));
XMLStreamReader xmlStreamReader = inputFactory.createXMLStreamReader(input);

while (xmlStreamReader.hasNext()) {
    int event = xmlStreamReader.next();

    if (event == XMLStreamConstants.START_ELEMENT) {
    System.out.println("Element Local Name:" + xmlStreamReader.getLocalName());
    }

    if (event == XMLStreamConstants.CHARACTERS) {
                        if(!xmlStreamReader.getText().trim().equals("")){
                        System.out.println("Text:"+xmlStreamReader.getText().trim());
                        }
                }

            }

Edit incorrect behaviour :

    Element Local Name:root
    Element Local Name:item
    Element Local Name:ItemID
    Text:4504216603
    Element Local Name:ListingDetails
    Element Local Name:StartTime
    Text:10:00:10.000Z
    Element Local Name:EndTime
    Text:10:00:30.000Z
    Element Local Name:ViewItemURL
    Text:http://url

I don't want that root and other nodes which don't have text to be printed, just the output which I wrote above. thank you


Solution

  • Try this:

    while (xmlStreamReader.hasNext()) {
        int event = xmlStreamReader.next();
    
        if (event == XMLStreamConstants.START_ELEMENT) {
            try {
                String text = xmlStreamReader.getElementText();
                System.out.println("Element Local Name:" + xmlStreamReader.getLocalName());
                System.out.println("Text:" + text);
            } catch (XMLStreamException e) {
    
            }
        }
    
    }
    

    SAX based solution (works):

    public class Test extends DefaultHandler {
    
        public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException, XMLStreamException {
            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
            parser.parse(new File("src/file.xml"), new Test());
        }
    
        private String currentName;
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            currentName = qName;
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            String string = new String(ch, start, length);
            if (hasText(string)) {
                System.out.println(currentName);
                System.out.println(string);
            }
        }
    
        private boolean hasText(String string) {
            string = string.trim();
            return string.length() > 0;
        }
    }