Oracle XMLType - 迭代具有某些属性值的元素

Posted

技术标签:

【中文标题】Oracle XMLType - 迭代具有某些属性值的元素【英文标题】:Oracle XMLType - iterating over elements with certain attribute values 【发布时间】:2015-07-01 09:27:28 【问题描述】:

我在 Oracle 数据库的一个字段中存储了以下 xml:

Activity mc:Ignorable="sap sap2010 sads" x:Class="Process"
     xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
     xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:awaw="clr-namespace:A.Workflow.Activities.WSCall;assembly=A.Workflow.Activities"
     xmlns:awd="clr-namespace:A.Workflow.DataObjects;assembly=A.Workflow.DataObjects"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities"
     xmlns:sads="http://schemas.microsoft.com/netfx/2010/xaml/activities/debugger"
     xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation"
     xmlns:sap2010="http://schemas.microsoft.com/netfx/2010/xaml/activities/presentation"
     xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib"
     xmlns:sco="clr-namespace:System.Collections.ObjectModel;assembly=mscorlib"
     xmlns:sd="clr-namespace:System.Data;assembly=System.Data"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          x:Members
            x:Property Name="GlobalMessagesCollectionIn" Type="InArgument(awd:GlobalMessagesCollection)" />
            x:Property Name="EventDataCollectionIn" Type="InArgument(awd:DataFileCollection)" />
            x:Property Name="DocumentDataCollectionIn" Type="InArgument    (awd:DataFileCollection)" />
            x:Property Name="ResultDataCollectionIn" Type="InArgument    (awd:DataFileCollection)" />
            x:Property Name="BrokerRefIn" Type="InArgument(x:String)" />
            x:Property Name="ClientFeeRefIn" Type="InArgument(x:String)" />
            x:Property Name="InitUserTeamRefIn" Type="InArgument(x:String)" />
            x:Property Name="InitUserTeamNameIn" Type="InArgument(x:String)" />
            x:Property Name="InitUserBrokOffRefIn" Type="InArgument(x:String)" />
          /x:Members>
          mva:VisualBasic.Settings>
            <x:Null />
          /mva:VisualBasic.Settings>

        /Activity

我正在尝试编写 pl/sql 过程 - 假设为每个 x:Property 元素输出 @Name 属性值,其中 Name 属性包含子字符串 'In'。

以下是我解决问题的尝试:

declare 
p_ProcessFile xmltype;

BEGIN
 SELECT ProcessFile
      INTO p_ProcessFile
      FROM Process
     WHERE ProcessSeqNo = 4034; --This fetches the above xml into xmltype var

    FOR i IN (select p_ProcessFile.extract( '//x:Members/x:Property[(contains(@Name, "In")) ]/@Name', 'xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"').getStringVal() AS testing  FROM dual) LOOP
      dbms_output.put_line(i.testing || ';');
     END LOOP;

END;

不幸的是,这会输出所有连接的值:

GlobalMessagesCollectionInEventDataCollectionInDocumentDataCollectionInResultDataCollectionInBrokerRefIn;

但是,我想要的是:

GlobalMessagesCollectionIn
EventDataCollectionIn
DocumentDataCollectionIn
ResultDataCollectionIn
etc

如何使用包含“In”的@Name 属性对每个 x:Property 进行迭代?

【问题讨论】:

【参考方案1】:

也许值得注意的是 XMLSEQUNCE 已被弃用。

您可以在纯 SQL 中获得相同的结果 - 无需 PL/SQL 块或循环 - 使用 XMLTABLE

select x.name
from process p
cross join xmltable(
  xmlnamespaces('http://schemas.microsoft.com/winfx/2006/xaml' as "x"),
  '//x:Property[(contains(@Name, "In"))]'
  passing p.processfile
  columns name varchar2(30) path '@Name'
) x
where p.processseqno = 4034;

NAME                         
------------------------------
GlobalMessagesCollectionIn    
EventDataCollectionIn         
DocumentDataCollectionIn      
ResultDataCollectionIn        
BrokerRefIn                   
ClientFeeRefIn                
InitUserTeamRefIn             
InitUserTeamNameIn            
InitUserBrokOffRefIn          

【讨论】:

【参考方案2】:

XML序列。用这个替换你的 for 循环。

for i in (   SELECT VALUE(p).extract('//x:Property[(contains(@Name, "In"))]/@Name', 'xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"').getStringVal() val
   FROM TABLE(XMLSEQUENCE(EXTRACT(p_ProcessFile,  '//x:Members/x:Property[(contains(@Name, "In"))]', 'xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"'))) p  ) loop
  dbms_output.put_line(i.val); 
end loop;

【讨论】:

谢谢你的救星。那么,它是否有效,因为 XMLSequence 将所有元素转换为“单独的”xml 文档数组?

以上是关于Oracle XMLType - 迭代具有某些属性值的元素的主要内容,如果未能解决你的问题,请参考以下文章

拆分 XMLTYPE 以根据条件创建两个 XMLTYPE

如何在 oracle XMLTYPE XMLTABLE 中支持 1 级路径目录

Oracle-XMLTYPE:如何更新值

oracle, xmltype/clob substr 循环

将 oracle xmltype 表字段选择到 xmltype 变量中会导致空对象

初识Oracle的XMLType