package eu.simstadt.lowlevelgmlparser; import java.io.IOException; import java.nio.file.Path; import java.util.Iterator; import java.util.logging.Logger; import com.ximpleware.AutoPilot; import com.ximpleware.NavException; import com.ximpleware.VTDGen; import com.ximpleware.VTDNav; import com.ximpleware.XPathEvalException; import com.ximpleware.XPathParseException; public class CityGmlIterator implements Iterable { private static final Logger LOGGER = Logger.getLogger(CityGmlIterator.class.getName()); private AutoPilot buildingsFinder; private VTDNav navigator; private long offsetAndLength; private int buildingsCount = 0; private int buildingOffset = 0; private int buildingLength = 0; public CityGmlIterator(Path citygmlPath) throws XPathParseException, NavException, NumberFormatException, XPathEvalException, IOException { VTDGen parser = new VTDGen(); parser.parseFile(citygmlPath.toString(), false); this.navigator = parser.getNav(); this.buildingsFinder = new AutoPilot(navigator); buildingsFinder.selectXPath("//cityObjectMember"); } @Override public Iterator iterator() { Iterator it = new Iterator() { @Override public boolean hasNext() { try { return buildingsFinder.evalXPath() != -1; } catch (XPathEvalException | NavException ex) {} return false; } @Override public BuildingXmlNode next() { try { buildingsCount += 1; if (buildingsCount % 1000 == 0) { LOGGER.info("1000 buildings parsed"); } offsetAndLength = navigator.getElementFragment(); buildingOffset = (int) offsetAndLength; buildingLength = (int) (offsetAndLength >> 32); return new BuildingXmlNode(navigator, buildingOffset, buildingLength); } catch (NavException ex) {} return null; } @Override public void remove() { throw new UnsupportedOperationException(); } }; return it; } }