saxpath
saxpath copied to clipboard
Ability to match multiple, different elements?
Is it possible to match against multiple, different elements without needing to create 2 stream parsers? Or, are multiple parsers on the same stream the 'right' way to do this?
For example, in the attached XML I'd like to retrieve both the gml:Envelope
and cityObjectMember
elements. As things stand I can only do this by creating 2 parsers each with separate event handlers, like so:
var saxStreamEnvelope = new saxpath.SaXPath(saxParser, "//gml:Envelope");
saxStreamEnvelope.on("match", function (xml) { ... });
var saxStreamCity = new saxpath.SaXPath(saxParser, "//cityObjectMember");
saxStreamCity.on("match", function (xml) { ... });
XML:
<?xml version="1.0" encoding="utf-8"?>
<!-- CityGML Version No. 2.0, February 2012 -->
<!-- CityGML - GML 3.1.1 application schema for 3D city models -->
<!-- International encoding standard of the Open Geospatial Consortium, see http://www.opengeospatial.org/standards/citygml -->
<!-- Jointly developed by the Special Interest Group 3D (SIG 3D) of GDI-DE, see http://www.sig3d.org -->
<!-- For further information see: http://www.citygml.org -->
<CityModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.opengis.net/citygml/2.0"
xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:gml="http://www.opengis.net/gml" xmlns:dem="http://www.opengis.net/citygml/relief/2.0"
xmlns:bldg="http://www.opengis.net/citygml/building/2.0"
xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd">
<gml:name>Simple 3D city model LOD1 without Appearance</gml:name>
<gml:boundedBy>
<gml:Envelope srsDimension="3" srsName="urn:ogc:def:crs,crs:EPSG::25832,crs:EPSG::5783">
<gml:lowerCorner>458868.0 5438343.0 112.0</gml:lowerCorner>
<gml:upperCorner>458892.0 5438362.0 117.0</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<cityObjectMember>
<bldg:Building gml:id="GML_7b1a5a6f-ddad-4c3d-a507-3eb9ee0a8e68">
<gml:name>Example Building LOD1 </gml:name>
<bldg:function codeSpace="http://www.sig3d.org/codelists/standard/building/2.0/_AbstractBuilding_function.xml">1000</bldg:function>
<bldg:yearOfConstruction>1985</bldg:yearOfConstruction>
<bldg:roofType codeSpace="http://www.sig3d.org/codelists/standard/building/2.0/_AbstractBuilding_roofType.xml">1030</bldg:roofType>
<bldg:measuredHeight uom="#m">5.0</bldg:measuredHeight>
<bldg:storeysAboveGround>1</bldg:storeysAboveGround>
<bldg:storeyHeightsAboveGround uom="#m">3.0</bldg:storeyHeightsAboveGround>
<bldg:lod1Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface gml:id="lod1Surface">
<!-- Face Side 1 -->
<gml:surfaceMember>
<gml:Polygon>
<gml:exterior>
<gml:LinearRing>
<gml:posList>458875.0 5438350.0 112.0 458885.0 5438350.0 112.0 458885.0 5438350.0 116.0 458875.0 5438350.0
116.0 458875.0 5438350.0 112.0 </gml:posList>
</gml:LinearRing>
</gml:exterior
</gml:Polygon>
</gml:surfaceMember>
<!-- Face Side 2 -->
<gml:surfaceMember>
<gml:Polygon>
<gml:exterior>
<gml:LinearRing>
<gml:posList>458885.0 5438350.0 112.0 458885.0 5438355.0 112.0 458885.0 5438355.0 116.0 458885.0 5438350.0
116.0 458885.0 5438350.0 112.0 </gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<!-- Face Side 3 -->
<gml:surfaceMember>
<gml:Polygon>
<gml:exterior>
<gml:LinearRing>
<gml:posList>458885.0 5438355.0 112.0 458875.0 5438355.0 112.0 458875.0 5438355.0 116.0 458885.0 5438355.0
116.0 458885.0 5438355.0 112.0 </gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<!-- Face Side 4 -->
<gml:surfaceMember>
<gml:Polygon>
<gml:exterior>
<gml:LinearRing>
<gml:posList>458875.0 5438355.0 112.0 458875.0 5438350.0 112.0 458875.0 5438350.0 116.0 458875.0 5438355.0
116.0 458875.0 5438355.0 112.0 </gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<!-- Face Top -->
<gml:surfaceMember>
<gml:Polygon>
<gml:exterior>
<gml:LinearRing>
<gml:posList>458875.0 5438350.0 116.0 458885.0 5438350.0 116.0 458885.0 5438355.0 116.0 458875.0 5438355.0
116.0 458875.0 5438350.0 116.0 </gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<!-- Face Bottom -->
<gml:surfaceMember>
<gml:Polygon>
<gml:exterior>
<gml:LinearRing>
<gml:posList>458875.0 5438350.0 112.0 458875.0 5438355.0 112.0 458885.0 5438355.0 112.0 458885.0 5438350.0
112.0 458875.0 5438350.0 112.0 </gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod1Solid>
</bldg:Building>
</cityObjectMember>
<cityObjectMember>...</cityObjectMember>
<cityObjectMember>...</cityObjectMember>
<cityObjectMember>...</cityObjectMember>
</CityModel>
Thank you for the report. At this moment it is not possible to do this and you'll have to create to separate event handlers.
Can you give an example XPath-expression on how to match both elements? Maybe SAXPath can be extended to support matching different elements.
On Thu, Apr 30, 2015 at 3:03 PM, Robin Hawkes [email protected] wrote:
Is it possible to match against multiple, different elements without needing to create 2 stream parsers? Or, are multiple parsers on the same stream the 'right' way to do this?
For example, in the attached XML I'd like to retrieve both the gml:Envelope and cityObjectMember elements. As things stand I can only do this by creating 2 parsers each with separate event handlers, like so:
var saxStreamEnvelope = new saxpath.SaXPath(saxParser, "//gml:Envelope"); saxStreamEnvelope.on("match", function (xml) { ... }); var saxStreamCity = new saxpath.SaXPath(saxParser, "//cityObjectMember"); saxStreamCity.on("match", function (xml) { ... });
XML:
<CityModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.opengis.net/citygml/2.0" xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:gml="http://www.opengis.net/gml" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd"> gml:nameSimple 3D city model LOD1 without Appearance/gml:name gml:boundedBy <gml:Envelope srsDimension="3" srsName="urn:ogc:def:crs,crs:EPSG::25832,crs:EPSG::5783"> gml:lowerCorner458868.0 5438343.0 112.0/gml:lowerCorner gml:upperCorner458892.0 5438362.0 117.0/gml:upperCorner /gml:Envelope /gml:boundedBy <cityObjectMember> <bldg:Building gml:id="GML_7b1a5a6f-ddad-4c3d-a507-3eb9ee0a8e68"> gml:nameExample Building LOD1 /gml:name <bldg:function codeSpace="http://www.sig3d.org/codelists/standard/building/2.0/_AbstractBuilding_function.xml">1000/bldg:function bldg:yearOfConstruction1985/bldg:yearOfConstruction <bldg:roofType codeSpace="http://www.sig3d.org/codelists/standard/building/2.0/_AbstractBuilding_roofType.xml">1030/bldg:roofType <bldg:measuredHeight uom="#m">5.0/bldg:measuredHeight bldg:storeysAboveGround1/bldg:storeysAboveGround <bldg:storeyHeightsAboveGround uom="#m">3.0/bldg:storeyHeightsAboveGround bldg:lod1Solid gml:Solid gml:exterior <gml:CompositeSurface gml:id="lod1Surface"> gml:surfaceMember gml:Polygon gml:exterior gml:LinearRing gml:posList458875.0 5438350.0 112.0 458885.0 5438350.0 112.0 458885.0 5438350.0 116.0 458875.0 5438350.0 116.0 458875.0 5438350.0 112.0 /gml:posList /gml:LinearRing </gml:exterior </gml:Polygon> /gml:surfaceMember gml:surfaceMember gml:Polygon gml:exterior gml:LinearRing gml:posList458885.0 5438350.0 112.0 458885.0 5438355.0 112.0 458885.0 5438355.0 116.0 458885.0 5438350.0 116.0 458885.0 5438350.0 112.0 /gml:posList /gml:LinearRing /gml:exterior /gml:Polygon /gml:surfaceMember gml:surfaceMember gml:Polygon gml:exterior gml:LinearRing gml:posList458885.0 5438355.0 112.0 458875.0 5438355.0 112.0 458875.0 5438355.0 116.0 458885.0 5438355.0 116.0 458885.0 5438355.0 112.0 /gml:posList /gml:LinearRing /gml:exterior /gml:Polygon /gml:surfaceMember gml:surfaceMember gml:Polygon gml:exterior gml:LinearRing gml:posList458875.0 5438355.0 112.0 458875.0 5438350.0 112.0 458875.0 5438350.0 116.0 458875.0 5438355.0 116.0 458875.0 5438355.0 112.0 /gml:posList /gml:LinearRing /gml:exterior /gml:Polygon /gml:surfaceMember gml:surfaceMember gml:Polygon gml:exterior gml:LinearRing gml:posList458875.0 5438350.0 116.0 458885.0 5438350.0 116.0 458885.0 5438355.0 116.0 458875.0 5438355.0 116.0 458875.0 5438350.0 116.0 /gml:posList /gml:LinearRing /gml:exterior /gml:Polygon /gml:surfaceMember gml:surfaceMember gml:Polygon gml:exterior gml:LinearRing gml:posList458875.0 5438350.0 112.0 458875.0 5438355.0 112.0 458885.0 5438355.0 112.0 458885.0 5438350.0 112.0 458875.0 5438350.0 112.0 /gml:posList /gml:LinearRing /gml:exterior /gml:Polygon /gml:surfaceMember /gml:CompositeSurface /gml:exterior /gml:Solid /bldg:lod1Solid /bldg:Building </cityObjectMember> <cityObjectMember>...</cityObjectMember> <cityObjectMember>...</cityObjectMember> <cityObjectMember>...</cityObjectMember> </CityModel>
— Reply to this email directly or view it on GitHub https://github.com/StevenLooman/saxpath/issues/13.
That'd be really helpful if these operators can be added. From what I can see, the nearest XPath expression would be the pipe operator, as described here:
- https://msdn.microsoft.com/en-us/library/ms256081%28v=vs.110%29.aspx
- http://www.w3.org/TR/xpath/#node-sets
- http://stackoverflow.com/a/20122323/997339
- http://stackoverflow.com/questions/5350666/xpath-or-operator-for-different-nodes
For example, the following will return both elements (as can be tested here):
//gml:Envelope | //cityObjectMember
Ok, I'll see what I can do.