首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PLSQL解析GML

PLSQL解析GML
EN

Stack Overflow用户
提问于 2020-02-26 08:05:30
回答 1查看 129关注 0票数 0

试图优化将GML字符串解析到Oracle sdo_geometry的过程。

代码语言:javascript
运行
复制
<gml:Polygon >
   <gml:exterior>
        <gml:LinearRing>
            <gml:posList > [coordinates] </gml:posList>
        </gml:LinearRing>
    </gml:exterior>
   <gml:interior>
        <gml:Ring>
             <gml:curveMember>
                <gml:Curve>
                    <gml:segments>
                        <gml:LineStringSegment>
                            <gml:posList > [coordinates] </gml:posList>
                        </gml:LineStringSegment>
                        <gml:Arc>
                            <gml:posList > [coordinates] </gml:posList>
                        </gml:Arc>
                        <gml:LineStringSegment>
                            <gml:posList > ... </gml:posList>
                        </gml:LineStringSegment>
                    </gml:segments>
                </gml:Curve>
            </gml:curveMember>
        </gml:Ring>
    </gml:interior>
   <gml:interior>
        <gml:LinearRing>
            <gml:posList > [coordinates] </gml:posList>
        </gml:LinearRing>
    </gml:interior> 
</gml:Polygon>

多边形由一个外部元素和0到多个内部元素组成.

我们目前的解决方案如下所示。

首先,它提取所有外部和内部元素,并分别处理这些元素。

代码语言:javascript
运行
复制
 cursor c_exterior(p_xml xmltype) is
         select t.*
           from xmltable('//exterior' passing p_xml columns exterior xmltype path '/') as t;

      cursor c_interior(p_xml xmltype) is
         select t.*
           from xmltable('//interior' passing p_xml columns interior xmltype path '/') as t;

   begin

      -- process each exterior/interior ring.   
      for r_exterior in c_exterior(p_xml)
      loop
         process(r_exterior.exterior, [other params]);
      end loop;

      for r_interior in c_interior(p_xml)
      loop
         process(r_interior.interior, [other params]);
      end loop;

外部和内部元素的处理如下:

代码语言:javascript
运行
复制
   select t.*
   from xmltable('for $d in //node() where exists($d/posList) return $d' passing p_xml columns
                            poslist clob path './posList'
                            ,parent varchar2(100) path 'name()') as t;

这将获取坐标列表和poslist元素的直系亲属的名称。

问:由于这是一个两步的过程,它可能没有优化的速度。我正在寻找从1查询中从GML获取所需信息的方法。但我不知道该怎么做。主要是由于poslist元素的XML级别的变化和生成外部/内部环的数量。

我需要的信息:

  1. 外部或内部。环的
  2. 数。所以我知道坐标是同一个外部/内部环的一部分。
  3. 坐标poslist元素的直系亲属的
  4. 名称.

所以从上面的例子来看:

代码语言:javascript
运行
复制
exterior, 1, gml:LinearRing, [coordinates]
interior, 2, gml:LineStringSegment, [coordinates]
interior, 2, gml:Arc, [coordinates]
interior, 2, gml:LineStringSegment, [coordinates]
interior, 3, gml:LinearRing, [coordinates]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-26 08:52:23

您可以使用链接的XMLTable调用:

代码语言:javascript
运行
复制
select x1.type, x1.ring_num, x2.parent, x2.coordinates
from xmltable(
  xmlnamespaces(default 'http://www.opengis.net/gml/'),
  '/Polygon/*'
  passing p_xml
  columns type varchar2(8) path './local-name()',
    ring_num for ordinality,
    nodes xmltype path '//posList/..'
) x1
cross join xmltable (
  xmlnamespaces(default 'http://www.opengis.net/gml/'),
  '/*'
  passing x1.nodes
  columns parent varchar2(21) path './name()',
    coordinates varchar2(30) path 'posList'
) x2;

(当然,根据实际数据的需要调整输出数据类型和大小)

x1表获取外部/内部节点,为“环数”添加一个序号列,并包含一个XMLType列,该列包含所有作为posList节点父节点的节点。然后将其传递到x2,后者提取多个posList坐标和父节点。

使用CTE提供XML文档而不是PL/SQL的演示:

代码语言:javascript
运行
复制
with t (p_xml) as (
  select xmltype('<gml:Polygon xmlns:gml="http://www.opengis.net/gml/">
   <gml:exterior>
        <gml:LinearRing>
            <gml:posList > [coordinates] </gml:posList>
        </gml:LinearRing>
    </gml:exterior>
   <gml:interior>
        <gml:Ring>
             <gml:curveMember>
                <gml:Curve>
                    <gml:segments>
                        <gml:LineStringSegment>
                            <gml:posList > [coordinates] </gml:posList>
                        </gml:LineStringSegment>
                        <gml:Arc>
                            <gml:posList > [coordinates] </gml:posList>
                        </gml:Arc>
                        <gml:LineStringSegment>
                            <gml:posList > ... </gml:posList>
                        </gml:LineStringSegment>
                    </gml:segments>
                </gml:Curve>
            </gml:curveMember>
        </gml:Ring>
    </gml:interior>
   <gml:interior>
        <gml:LinearRing>
            <gml:posList > [coordinates] </gml:posList>
        </gml:LinearRing>
    </gml:interior> 
</gml:Polygon>') from dual
)
select x1.type, x1.ring_num, x2.parent, x2.coordinates
from t
cross join xmltable(
  xmlnamespaces(default 'http://www.opengis.net/gml/'),
  '/Polygon/*'
  passing t.p_xml
  columns type varchar2(8) path './local-name()',
    ring_num for ordinality,
    nodes xmltype path '//posList/..'
) x1
cross join xmltable (
  xmlnamespaces(default 'http://www.opengis.net/gml/'),
  '/*'
  passing x1.nodes
  columns parent varchar2(21) path './name()',
    coordinates varchar2(30) path 'posList'
) x2;

这会得到:

代码语言:javascript
运行
复制
TYPE       RING_NUM PARENT                COORDINATES                   
-------- ---------- --------------------- ------------------------------
exterior          1 gml:LinearRing         [coordinates]                
interior          2 gml:LineStringSegment  [coordinates]                
interior          2 gml:Arc                [coordinates]                
interior          2 gml:LineStringSegment  ...                          
interior          3 gml:LinearRing         [coordinates]                

name()local-name()之间切换,可以从值中包含或省略命名空间。

您也可以使用单个XMLTable来实现这一点,但是获得“环号”有点痛苦;这里我正在向外部/内部节点注入一个属性--这可能比链接的XMLTable方法慢,但可能值得对您的数据进行测试:

代码语言:javascript
运行
复制
select x.type, x.ring_num, x.parent, x.coordinates
from xmltable(
  xmlnamespaces(default 'http://www.opengis.net/gml/'),
  'copy $i := /Polygon
    modify
      for $j in $i/(exterior | interior)
        return (insert node attribute pos { count($j/preceding-sibling::*) + 1 } into $j)
    return $i//posList'
  passing t.p_xml
  columns type varchar2(8) path 'local-name(./ancestor::exterior | ./ancestor::interior)',
    ring_num number path '(./ancestor::exterior/@pos | ./ancestor::interior/@pos)',
    parent varchar2(21) path '../name()',
    coordinates varchar2(30) path '.'
) x;

使用CTE再次对示例数据进行处理,得到相同的结果。我不确定是否有另一种有效的方法- FLWOR循环中的迭代计数。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60409333

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档