Oracle XML 解析表多个子元素

Posted

技术标签:

【中文标题】Oracle XML 解析表多个子元素【英文标题】:Oracle XML Parse to Table Multiple Sub Elements 【发布时间】:2020-07-01 18:18:21 【问题描述】:

您好,我有一个 xml 字符串,我想将其解析为表。问题是当我在 xml 中有多个子类别时,它会引发异常。

[错误] 执行 (27: 35):ORA-19279: XPTY0004 - XQuery 动态类型不匹配:预期的单例序列 - 得到多项序列

MasaPersonelUrunleri, MasaPersonel 可以不止一个。当我在下面编写单个查询时,每个查询都有效,但是当我再添加一个元素时,它会引发错误。怎样才能解决问题?

select *  
FROM XMLTABLE('/Masa'  
         PASSING   
            xmltype('
               <Masa>
                    <ID>0</ID>
                    <SICIL>60950</SICIL>
                    <TARIH>2020-03-20T17:00:03</TARIH>
                    <IS_KERZZ>0</IS_KERZZ>
                    <MASA>
                        <MasaPersonel>
                            <SICIL>60950</SICIL>
                            <AD_SOYAD>Test User</AD_SOYAD>
                            <TOTAL>0</TOTAL>
                            <MASA_ID>0</MASA_ID>
                            <RESERVATION_ID>0</RESERVATION_ID>
                            <ID>0</ID>
                            <URUNLER>
                                <MasaPersonelUrunleri>
                                    <ID>0</ID>
                                    <ADET>1</ADET>
                                    <BIRIM_FIYAT>20</BIRIM_FIYAT>
                                    <SICIL>60950</SICIL>
                                    <URUN_KOD>URN284</URUN_KOD>
                                    <URUN_AD>IZGARA PİLİÇ</URUN_AD>
                                </MasaPersonelUrunleri>
                                <MasaPersonelUrunleri>
                                    <ID>0</ID>
                                    <ADET>1</ADET>
                                    <BIRIM_FIYAT>25</BIRIM_FIYAT>
                                    <SICIL>60950</SICIL>
                                    <URUN_KOD>URN285</URUN_KOD>
                                    <URUN_AD>TAVUK PİLİÇ</URUN_AD>
                                </MasaPersonelUrunleri>
                            </URUNLER>
                        </MasaPersonel>
                    </MASA>
                </Masa>
            ')
         COLUMNS  
            --describe columns and path to them:  
            SICIL  varchar2(20)    PATH './SICIL',  
            TARIH varchar2(20)     PATH './TARIH',
            PERSONEL  varchar2(20) PATH './MASA/MasaPersonel/SICIL',
            URUN_KODU varchar2(20) PATH './MASA/MasaPersonel/URUNLER/MasaPersonelUrunleri/URUN_KOD',
            URUN_ADI varchar2(20)  PATH './MASA/MasaPersonel/URUNLER/MasaPersonelUrunleri/URUN_AD',
            URUN_ADETI number      PATH './MASA/MasaPersonel/URUNLER/MasaPersonelUrunleri/ADET',
            URUN_FIYATI number     PATH './MASA/MasaPersonel/URUNLER/MasaPersonelUrunleri/BIRIM_FIYAT'
     ) xmlt  
;  

【问题讨论】:

【参考方案1】:

您可以使用链式 XMLTable 调用,但在这种情况下,您可以让您的 XPath 进入多元素级别:

select *  
FROM XMLTABLE('/Masa/MASA/MasaPersonel/URUNLER/MasaPersonelUrunleri'  

然后调整列路径以返回树:

         COLUMNS  
            --describe columns and path to them:  
            SICIL  varchar2(20)    PATH './../../../../SICIL',  
            TARIH varchar2(20)     PATH './../../../../TARIH',
            PERSONEL  varchar2(20) PATH './../../SICIL',
            URUN_KODU varchar2(20) PATH 'URUN_KOD',
            URUN_ADI varchar2(20)  PATH 'URUN_AD',
            URUN_ADETI number      PATH 'ADET',
            URUN_FIYATI number     PATH 'BIRIM_FIYAT'
     ) xmlt  
;  

得到:

SICIL                TARIH                PERSONEL             URUN_KODU            URUN_ADI             URUN_ADETI URUN_FIYATI
-------------------- -------------------- -------------------- -------------------- -------------------- ---------- -----------
60950                2020-03-20T17:00:03  60950                URN284               IZGARA PİLİÇ                  1          20
60950                2020-03-20T17:00:03  60950                URN285               TAVUK PİLİÇ                   1          25

db<>fiddle


链式 XMLTable 方法类似于:

select xml1.SICIL, xml1.TARIH, xml1.PERSONEL, xml2.URUN_KODU, xml2.URUN_ADI, xml2.URUN_ADETI, xml2.URUN_FIYATI
FROM XMLTABLE('/Masa'  
...
         COLUMNS  
            --describe columns and path to them:  
            SICIL  varchar2(20)    PATH './SICIL',  
            TARIH varchar2(20)     PATH './TARIH',
            PERSONEL  varchar2(20) PATH './MASA/MasaPersonel/SICIL',
            URUNLERI xmltype       PATH './MASA/MasaPersonel/URUNLER/MasaPersonelUrunleri'
    ) xml1
CROSS JOIN XMLTABLE ('/MasaPersonelUrunleri'
         PASSING xml1.URUNLERI
         COLUMNS  
            URUN_KODU varchar2(20) PATH './URUN_KOD',
            URUN_ADI varchar2(20)  PATH './URUN_AD',
            URUN_ADETI number      PATH './ADET',
            URUN_FIYATI number     PATH './BIRIM_FIYAT'
     ) xml2  
;  

每个 XMLTable 生成一些列的位置;多项目序列是它们之间的链接,从第一个 XMLTable 中提取并传递到第二个。

db<>fiddle

PERSONEL varchar2(20) PATH './MASA/MasaPersonel/SICIL' 在有多个 MASA/MasaPersonel 节点时会导致问题

问题的示例中没有显示,但您可以使用另一个链接的 XMLTable 来处理它:

select xml1.SICIL, xml1.TARIH, xml2.PERSONEL, xml3.URUN_KODU, xml3.URUN_ADI, xml3.URUN_ADETI, xml3.URUN_FIYATI
FROM XMLTABLE('/Masa'  
...
         COLUMNS  
            --describe columns and path to them:  
            SICIL  varchar2(20)    PATH './SICIL',  
            TARIH varchar2(20)     PATH './TARIH',
            MASAPERSONEL xmltype   PATH './MASA/MasaPersonel'
    ) xml1
CROSS JOIN XMLTABLE ('/MasaPersonel'
         PASSING xml1.MASAPERSONEL
         COLUMNS  
            PERSONEL varchar2(20)  PATH './SICIL',
            URUNLERI xmltype       PATH './URUNLER/MasaPersonelUrunleri'
     ) xml2  
CROSS JOIN XMLTABLE ('/MasaPersonelUrunleri'
         PASSING xml2.URUNLERI
         COLUMNS  
            URUN_KODU varchar2(20) PATH './URUN_KOD',
            URUN_ADI varchar2(20)  PATH './URUN_AD',
            URUN_ADETI number      PATH './ADET',
            URUN_FIYATI number     PATH './BIRIM_FIYAT'
     ) xml3
;  

db<>fiddle

【讨论】:

PERSONEL varchar2(20) PATH './MASA/MasaPersonel/SICIL' 当您有多个 MASA/MasaPersonel 节点时会导致问题。 当然,但问题中没有显示这种情况。如果这是一个问题,那么它需要链中的另一个 XMLTable。

以上是关于Oracle XML 解析表多个子元素的主要内容,如果未能解决你的问题,请参考以下文章

Python将XML解析为缺少元素的CSV

Apache XMLSchema 核心 XSD/XML 解析器将根元素显示为所有子元素的父元素,而不是其直接父元素

在 Java 中解析 XML 时有多余的子元素

按名称仅获取 XML 直接子元素

(PHP) 使用命名空间前缀附加新的 XML 子元素

在XSL上解析具有相同名称的子元素