【问题标题】:Reading XML element occurrences using PL SQL使用 PL SQL 读取 XML 元素的出现
【发布时间】:2015-02-25 12:06:03
【问题描述】:

我有这个 XML。

<a>
   <b>b1</b>
   <c>c1</c>
   <b>b2</b>
   <c>c2</c2>
</a>

我希望能够使用 PL\SQL 提取元素“b”和“c”的值。我正在使用 Oracle 10g。

到目前为止,我有这个,

  SELECT   XML.b                    
       , XML.c
    FROM XMLTable (
           '/a' PASSING p_xml
              COLUMNS
                 b            VARCHAR(2) PATH 'b/.'
               , c            VARCHAR(2) PATH 'c/.'
    ) XML

但我不断收到此错误:

19279. 00000 -  "XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence" 
*Cause:    The XQuery sequence passed in had more than one item.
*Action:   Correct the XQuery expression to return a single item sequence.

然后我尝试了这个:

  SELECT   XML.b                    
         , XML1.c
    FROM XMLTable (
           '/a/b' PASSING p_xml
              COLUMNS
                 b            VARCHAR(2) PATH '.'
    ) XML,
        XMLTable (
           '/a/c' PASSING p_xml
              COLUMNS
                 c            VARCHAR(2) PATH '.'
    ) XML1

但结果是:

b1,c1
b1,c2
b2,c1
b2,c2

当我只想: b1 c1 b2 c2

你们能帮帮我吗?

【问题讨论】:

    标签: oracle plsql oracle10g xmltable oracle-xml-db


    【解决方案1】:

    我没有运行它,但据我所知,下面的代码应该可以工作;

    DECLARE
    vs_Xml VARCHAR2(32000):= '<INPUT>
      <A>
        <B>1</B>
      </A>
      <A>
        <B>2</B>
      </A>
    </INPUT>';
    
    vx_ParameterList   XMLTYPE;
    vx_Parameter       XMLTYPE;
    vn_ParameterIndex  NUMBER;
    vs_Key             VARCHAR2(64);
    vs_XPath           VARCHAR2(255);
    vs_Value           VARCHAR2(10000);
    
    BEGIN
    vx_ParameterList := xmltype(vs_Xml);
    vn_ParameterIndex := 1;
    vs_XPath := '/INPUT/A'; 
    
    WHILE vx_ParameterList.existsNode(vs_XPath || '[' || vn_ParameterIndex || ']') = 1 LOOP
      vx_Parameter := vx_ParameterList.extract(vs_XPath || '[' || vn_ParameterIndex || ']');
    
      vs_Value := vx_Parameter.extract('//B/text()').GetStringVal();
      vn_ParameterIndex := vn_ParameterIndex + 1;
    
      dbms_output.put_line(vs_Value);
    END
    

    【讨论】:

      【解决方案2】:

      您必须在XMLTABLE 命令中调整xquery 表达式。基本思想是产生一个 xml 记录流,每条记录都可以映射到数据库记录的列。

      原始xml中的障碍是xpath轴/a返回-措辞草率-所有 xml记录的内容。

      解决方案是在 /a 上构建一个迭代器,以逐个传递 xml 记录(技术上:包装在合成的 x 元素中)。

      以下可以从sqlplus发出:

            SELECT   myxml.b
                 ,   myxml.c                            
              FROM XMLTable (
      'for $i in (1, let $x := fn:count(/a/b) return $x )
       let $b := /a/b[$i], $c := /a/c[$i]
       return <x>
                 <b>{$b}</b>
                 <c>{$c}</c>
              </x>
      ' PASSING XMLTYPE(
      '<a>
         <b>b1</b>
         <c>c1</c>
         <b>b2</b>
         <c>c2</c>
      </a>')
                        COLUMNS
                           b            VARCHAR(2) PATH '/x/b'
                         , c            VARCHAR(2) PATH '/x/c'
              ) myxml
      ;
      

      更新

      为了允许任意数量的b/c 孩子,下面这行

      for $i in (1, let $x := fn:count(/a/b) return $x )
      

      替换原来的

      for $i in (1, 2)
      

      在上面的表达式中。

      参考

      有关 XQuery 语法的更多信息可以在W3c spec 中找到(深度链接到所谓的 FWLOR 表达式的语法文档)。

      【讨论】:

        猜你喜欢
        • 2013-07-30
        • 2016-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-19
        • 2019-07-05
        • 1970-01-01
        相关资源
        最近更新 更多