saxpath icon indicating copy to clipboard operation
saxpath copied to clipboard

Ability to match multiple, different elements?

Open robhawkes opened this issue 9 years ago • 3 comments

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>

robhawkes avatar Apr 30 '15 13:04 robhawkes

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.

StevenLooman avatar May 01 '15 08:05 StevenLooman

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

robhawkes avatar May 01 '15 09:05 robhawkes

Ok, I'll see what I can do.

StevenLooman avatar May 05 '15 16:05 StevenLooman