Page 1 of 2 12 LastLast
Results 1 to 10 of 16

Thread: Reading mutilple element types with StaxEventItemReader

  1. #1
    Join Date
    Apr 2010
    Location
    Brazil
    Posts
    12

    Exclamation Reading mutilple element types with StaxEventItemReader

    Dear Friends,

    I need to read multiple types of elements from XML input and bind to objects. I believe that is possible using StaxEventItemReader, but i don't know how.

    If it's not possible, please, tell me how can I do that using other ItemReader? Or if necessary, suggestions of custom XMLItemReader implementations.

    Thanks from Brazil.

    Fabiano

  2. #2
    Join Date
    Dec 2005
    Location
    Lyon, France
    Posts
    311

    Default

    You need to configure your StaxEventItemReader and provide it with an Spring OXM Unmarshaller. The latter will convert XML fragments into domain objects. This is explained here. Note you can use any marshalling library supported by Spring OXM (XStream, JAXB2, etc.).

  3. #3
    Join Date
    Apr 2010
    Location
    Brazil
    Posts
    12

    Default

    Thank you for reply!

    I undestand you, but the configuration allows only one fragmentRootElementName. Because of that, i can't map other element type at the same reader.

    I have some Spring Batch samples using StaxEventItemReader, but in everyone, the author didn't use multiple input type.

  4. #4
    Join Date
    May 2010
    Posts
    1

    Default MultiFragmentStaxEventItemReader

    I had the same problem and came up with the following solution:

    Code:
    package x.y.z;
    
    import java.util.List;
    
    import javax.xml.namespace.QName;
    import javax.xml.stream.XMLEventReader;
    import javax.xml.stream.XMLStreamException;
    import javax.xml.stream.events.StartElement;
    
    import org.apache.commons.lang.Validate;
    import org.springframework.batch.item.xml.StaxEventItemReader;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.dao.DataAccessResourceFailureException;
    
    /**
     * An enhanced <code>StaxEventItemReader</code> to handle multiple node element
     * names that need to be extracted.
     * 
     * @author mazehnder
     */
    public class MultiFragmentStaxEventItemReader<T> extends StaxEventItemReader<T>
        implements InitializingBean {
    
      private List<String> fragmentRootElementNames;
      
      public void setFragmentRootElementNames(List<String> fragmentRootElementNames) {
        if (fragmentRootElementNames == null || fragmentRootElementNames.isEmpty()) {
          throw new IllegalArgumentException("At least one root element name must be provided");
        }
        // to satisfy super class's afterPropertiesSet
        super.setFragmentRootElementName(fragmentRootElementNames.get(0));
        this.fragmentRootElementNames = fragmentRootElementNames;
      }
      
      @Override
      protected boolean moveCursorToNextFragment(XMLEventReader reader) {
        try {
          while (true) {
            while (reader.peek() != null && !reader.peek().isStartElement()) {
              reader.nextEvent();
            }
            if (reader.peek() == null) {
              return false;
            }
            QName startElementName = ((StartElement) reader.peek()).getName();
            String elementName = startElementName.getLocalPart();
            if (fragmentRootElementNames.contains(elementName)) {
              return true;
            } else {
              reader.nextEvent();
            }
          }
        } catch (XMLStreamException e) {
          throw new DataAccessResourceFailureException("Error while reading from event reader", e);
        }
      }
      
      @Override
      public void afterPropertiesSet() throws Exception {
        super.afterPropertiesSet();
        Validate.notNull(fragmentRootElementNames, "Property fragmentRootElementNames must not be null");
        Validate.notEmpty(fragmentRootElementNames, "Property fragmentRootElementNames must not be empty");
      }
    }

  5. #5
    Join Date
    Apr 2010
    Location
    Brazil
    Posts
    12

    Default

    Okay! Thank you very much!

    I'm going to implement some tests!!!

  6. #6
    Join Date
    Feb 2008
    Location
    Belgium
    Posts
    23

    Default

    Pay attention that the implementation of MultiFragmentStaxEventItemReader does not support restart. jumpToItem is not overridden and the implementation provided by StaxEventItemReader is based on the first fragmentRootElementName.

  7. #7
    Join Date
    Mar 2012
    Posts
    3

    Default MultiFragmentStaxEventItemReader with restart

    hi there,

    Is it possible to make MultiFragmentStaxEventItemReader restartable? Make it restartable is a major issue in our project at the moment where we have to read complex xml files.

    Hope anyone has a clue.

    Thanks in advance!
    Wop

  8. #8
    Join Date
    Feb 2008
    Location
    Belgium
    Posts
    23

    Default

    Here is my implementation of jumpToItem(int itemIndex)
    Code:
    	@Override
    	protected void jumpToItem(int itemIndex) throws Exception {
    		for (int i = 0; i < itemIndex; i++) {
    			readToStartFragment();
    			readToEndFragment();
    		}
    	}
    
    	private void readToStartFragment() throws XMLStreamException {
    		while (true) {
    			XMLEvent nextEvent = eventReader.nextEvent();
    			if (nextEvent.isStartElement() 
    					&& fragmentRootElementNames.contains(((StartElement) nextEvent).getName().getLocalPart())) {
    				return;
    			}
    		}
    	}
    
    	private void readToEndFragment() throws XMLStreamException {
    		while (true) {
    			XMLEvent nextEvent = eventReader.nextEvent();
    			if (nextEvent.isEndElement()
    					&& fragmentRootElementNames.contains(((EndElement) nextEvent).getName().getLocalPart())) {
    				return;
    			}
    		}
    	}

  9. #9
    Join Date
    Mar 2012
    Posts
    3

    Default

    thank you very much. I think I can use that.
    the only thing that is not very clear to me at the moment is how, with reading complex xmlfiles, itemIndex (READ_COUNT) is set.
    Does the framework do that?
    Has it to be done programmatically?
    Is it configuration?

  10. #10
    Join Date
    Feb 2008
    Location
    Belgium
    Posts
    23

    Default

    Your class must extend AbstractItemCountingItemStreamItemReader.

    See the javadoc of AbstractItemCountingItemStreamItemReader for more info.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •