My favorites | Sign in
Project Logo
                
Search
for
Updated Sep 01, 2008 by danilo.tuler
TraversingXML  
Traversing XML using XmlBeans objects

The issue

FIXatdl schema defines the following structure:

<xs:element name="strategyPanel">
	<xs:complexType>
		<xs:sequence>
			<xs:element ref="strategyPanel" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="parameter" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
	</xs:complexType>
</xs:element>

With this schema the following XML is valid:

<strategyPanel>
	<strategyPanel name="panel0" />
	<strategyPanel name="panel1" />
	<parameter name="parameter0" />
	<parameter name="parameter1" />
	<strategyPanel name="panel2" />
</strategyPanel>

When I generate a XmlBeans parser using the xsd the following interface is generated:

public interface StrategyPanel {
	public StrategyPanel[] getStrategyPanelArray();
	public Parameter[] getParameterArray();
}

Using the arrays I can traverse sub-panels and sub-parameters, but how can I traverse through both following the order they appear in the XML (panel0, panel1, parameter0, parameter1, panel2)?

The solution

We can create an Iterator<Object> based on the fact that I have access to the org.w3c.Node object of a given StrategyPanel or Parameter (thanks to XmlBeans). I keep track of two cursors and move then correctly. Code below:

public class StrategyPanelIterator implements Iterator<Object> {
 
	private StrategyPanel panel;
 
	private int i;
 
	private int paramIndex;
 
	private int panelIndex;
 
	public StrategyPanelIterator(StrategyPanel panel) {
		this.panel = panel;
		this.i = 0;
		this.paramIndex = 0;
		this.panelIndex = 0;
	}
 
	@Override
	public boolean hasNext() {
		int length = panel.getDomNode().getChildNodes().getLength();
		return i < length;
	}
 
	/**
	 * Returns the current element. The user must check if it's an instanceof
	 * ParameterT or StrategyPanel.
	 */
	@Override
	public Object next() {
		Object ret = null;
		int length = panel.getDomNode().getChildNodes().getLength();
		while (i < length && ret == null) {
			// get i-child
			Node node = panel.getDomNode().getChildNodes().item(i);
 
			// se if it matches with current parameter node
			if (panel.getParameterArray().length > paramIndex) {
				Node parameterNode = panel.getParameterArray(paramIndex)
						.getDomNode();
				if (parameterNode != null && parameterNode.equals(node)) {
					// return it and goes to the next parameter
					ret = panel.getParameterArray(paramIndex);
					paramIndex++;
				}
			}
 
			// se if it matches with current panel node
			if (panel.getStrategyPanelArray().length > panelIndex) {
				Node panelNode = panel.getStrategyPanelArray(panelIndex)
						.getDomNode();
				if (panelNode != null && panelNode.equals(node)) {
					// return it and goes to the next parameter
					ret = panel.getStrategyPanelArray(panelIndex);
					panelIndex++;
				}
			}
 
			i++;
		}
		return ret;
	}
 
	@Override
	public void remove() {
		throw new RuntimeException("operation not supported");
	}
 
}

Now, to use this Iterator you must check if the returned Object is an instance of StrategyPanel or Parameter, like this:

Iterator<Object> it = new StrategyPanelIterator(panel);
while (it.hasNext()) {
	Object obj = it.next();
	if (obj instanceof Parameter) {
		// handle that
	} else if (obj instanceof StrategyPanel) {
		// handle that
	}
}

Sign in to add a comment
Hosted by Google Code