首页 > 解决方案 > 如何在 oracle XMLTable 的 xpath 中将外部函数作为变量传递

问题描述

我有一个这样的xml文件:

     <GroupList>
       <Group>           
        <Title>
          <Name>Computer</Name>
        <Title>
        <Type>
          <Name>Book</Name>
        </Type>                   
        <DataList>
          <DataElement>
            <Name>Comment</Name>
            <Type>text</Type>
            <Value>ABC</Value>
            <Ordinality>1</Ordinality>
          </DataElement>
          <DataElement>
            <Name>Location</Name>
            <Type>set</Type>
            <Value>123</Value>
            <Ordinality>1</Ordinality>
          </DataElement>
        </DataList>
       </Group>
     </GroupList>

我正在尝试将外部函数作为 xpath 中的变量传递,我需要获取 DataElment/Name ='Location' 值。

这是查询片段:

   SELECT *                   
            FROM wd,                                            
                XMLTABLE (                        
         'GroupList/Group[Title/Name=''Computer'']' 
          PASSING xmltype(wd.data), externalfunction as "i"
          COLUMNS 
                name VARCHAR2(200) PATH 'Title/Name'
               ,type VARCHAR2(200) PATH 'Type/Name'
               ,location VARCHAr2(200) PATH 'DataElementList/dataElement[$i]/Name'
               ,location_value VARCHAR2(200) PATH 'DataElementList/dataElement[$i]/Value'
              ) x 

外部函数返回一个数字,当我运行查询时,出现此错误:

    ORA-19112: error raised during evaluation: XVM-01008: [XPST0008] Invalid reference
    1   DataElementList/dataElement[$i]/Value

将变量 i 传递给 xpath 的正确方法是什么?谢谢您的帮助。

标签: oracleoracle11gxquery

解决方案


@Tina 不确定如何在单个查询中实现,但我已经通过循环拥有一个表来做到这一点。以下是可以通过程序完成的代码......我只是想分享它是否有帮助

create table  DataElement with fields  Name,  Type,value and   Ordinality

PROCEDURE GET_DataElement(
    in_xml_frag      IN     CLOB,
    in_table_name    IN     VARCHAR2,
    out_xml_rec     OUT    DataElement%ROWTYPE)
IS
    v_xml_rec DataElement%ROWTYPE;
    v_row_value    VARCHAR2(100);
    v_row_division CLOB ;
    v_xml SYS.XMLTYPE := XMLTYPE(in_xml_frag);

    CURSOR table_fields_rec
    IS
      SELECT column_name,
        data_length column_size,
        data_type,
        table_name
      FROM all_tab_columns
      WHERE TABLE_NAME = in_table_name
      ORDER BY column_id ASC;

BEGIN

    FOR rec IN table_fields_rec
    LOOP

        IF (v_xml.existsNode('/' || rec.table_name || '/' || rec.column_name || '/text()') = 1) THEN
            v_row_value := v_xml.EXTRACT('/' || rec.table_name || '/' || rec.column_name ||'/text()') .GETSTRINGVAL();

            v_row_value := COMMON_TOOLS.ELIMINATE_SPECIAL_CHRCTRS(v_row_value);
            CASE rec.column_name
            WHEN 'Name' THEN
                v_xml_rec.Name := v_row_value;
            WHEN 'Type' THEN
                v_xml_rec.Type := v_row_value;
            WHEN 'value' THEN
                v_xml_rec.value := v_row_value;
            WHEN 'Ordinality' THEN
                v_xml_rec.Ordinality := v_row_value;
            ELSE
               NULL;
            END CASE;
        ELSE
            NULL;
        END IF;
    END LOOP;
    out_xml_rec := v_xml_rec;
END GET_DataElement;

推荐阅读