【问题标题】:Using XMLTABLE and xquery to extract data from xml使用 XMLTABLE 和 xquery 从 xml 中提取数据
【发布时间】:2015-08-12 06:28:41
【问题描述】:

我有以下 XML:

<per:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.something.com/2014/11/bla/webservice.xsd"
    xmlns:per="http://www.something.com/2014/11/bla/person">
    <per:Initials>E.C.</per:Initials>
    <per:FirstName>Erik</per:FirstName>
    <per:LastName>Flipsen</per:LastName>
    <per:BirthDate>1980-07-01</per:BirthDate>
    <per:Gender>Male</per:Gender>
</per:Person>

我想从这个 xml 中提取一些 PL/SQL 中的数据。我想使用 XMLTABLE,因为 EXTRACT 和 EXTRACTVALUE 函数已被弃用。

我可以使用这个查询来提取数据:

select pers.Initials,
       pers.Firstname
    into lsInitials,
         lsFirstname
    from
    XMLTABLE ('*:Person' passing pxRequest
    columns Initials           PATH '*:Initials',
            Firstname          PATH '*:FirstName'
    )  pers;

我对命名空间使用通配符,因为我并不真正关心发送方对命名空间使用什么缩写,但我知道获取数据的确切路径。

有了这段代码,我有两件事让我困惑:

编辑:

我发现当我删除元素的命名空间并将它们设为大写时,它可以工作。因此,似乎列名需要与 xml 元素名称匹配才能使其工作。我还没有弄清楚如何使它与命名空间 XML 一起工作。

  • 文档还指出“对于除 FOR ORDINALITY 列之外的每个结果列,您必须指定列数据类型”,但是,没有它似乎可以正常工作。为列和我要获取数据的变量指定它似乎也有点多余。如果不指定数据类型可能会给我带来麻烦?

可运行代码示例:

SET SERVEROUTPUT ON;
DECLARE

    pxRequest xmltype := xmltype('<per:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                    xsi:schemaLocation="http://www.something.com/2014/11/bla/webservice.xsd"
                                    xmlns:per="http://www.something.com/2014/11/bla/person">
                                    <per:Initials>E.C.</per:Initials>
                                    <per:FirstName>Erik</per:FirstName>
                                    <per:LastName>Flipsen</per:LastName>
                                    <per:BirthDate>1980-01-01</per:BirthDate>
                                    <per:Gender>Male</per:Gender>
                                </per:Person>');
    lsInitials  varchar2(100);
    lsFirstname varchar2(100);                                


begin

    select pers.Initials,
           pers.Firstname
        into lsInitials,
             lsFirstname
        from
        XMLTABLE ('*:Person' passing pxRequest
        columns Initials           PATH '*:Initials',
                Firstname          PATH '*:FirstName'
        )  pers;


    dbms_output.put_line(lsInitials);
    dbms_output.put_line(lsFirstname);

end;                            

【问题讨论】:

    标签: oracle plsql xquery xmltable


    【解决方案1】:

    根据您的第一个问题,the documentation you linked 今天有关于省略 PATH

    可选的PATH 子句指定由XQuery 表达式字符串寻址的XQuery 结果部分将用作列内容。

    如果省略 PATH,则假定 XQuery 表达式列。例如:

    (... COLUMNS xyz)

    等价于

    XMLTable(... COLUMNS xyz PATH 'XYZ')

    您可以使用不同的 PATH 子句将 XQuery 结果拆分为不同的虚拟表列。

    xyz 列被假定为'XYZ' 的原因是因为默认情况下,Oracle 不区分大小写(默认为全大写)。如果您将列定义为"aBcD",则PATH 的值将被假定为'aBcD'


    关于指定数据类型的第二个问题:如果您要提取的数据始终是文本数据,那么您可能可以不指定数据类型而侥幸。

    但是,如果您开始处理日期、时间戳、浮点数等内容,那么您可能会遇到问题。您要么需要使用TO_* 函数手动转换它们,要么可以在列定义中指定它们的数据类型。如果你不这样做,Oracle 可以随意隐式转换它,但它感觉合适,这可能会产生意想不到的后果。

    【讨论】:

      【解决方案2】:

      参考文献:

      https://stackoverflow.com/a/9976068/377141

      How to parse xml by xmltable when using namespace in xml(Oracle)

      如果您在 xmltable 中加载命名空间元素,它应该会按预期工作:

      select results    
      from xmltable( 
        xmlnamespaces(
          default 'http://tempuri.org/',    
          'http://schemas.xmlsoap.org/soap/envelope/' as "soap" 
        ),    
        'soap:Envelope/soap:Body/addResponse' passing xmltype(v_xml) 
         columns results varchar(100) path './addResult')
      

      从您的示例中(您可能还需要提前注册您的架构/命名空间,但这应该是一次):

      select pers.Initials,
             pers.Firstname
          into lsInitials,
               lsFirstname
          from
          XMLTABLE (
            xmlnamespaces(
              default 'http://tempuri.org/',   
              'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
              'http://www.something.com/2014/11/bla/person' as "per" 
            ),
          passing pxRequest
          columns Initials           PATH '*:Initials',
                  Firstname          PATH '*:FirstName'
          )  pers;
      

      过去在 Oracle 的早期版本中工作的东西在 XML 方面不适用于 11g+,据我所见,Oracle 强烈验证/键入 XML 操作的输入/输出,而在以前的版本中您可以正常运行没有命名空间信息的正确 XQuery 操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-22
        • 2023-03-28
        相关资源
        最近更新 更多