简体   繁体   English

在 Oracle 中使用 XPath 和 XQuery 连接 XML 节点

[英]Concatenate XML nodes using XPath and XQuery in Oracle

I have a XML data stored in CLOB column as follows:我有一个 XML 数据存储在 CLOB 列中,如下所示:

<row id='123456' xml:space='preserve'>
<name>Martin H</name>
<phone>1111</phone>
<phone m='2'>2222</phone>
<phone m='3'></phone>
<sms m='2'>1212</sms>
<sms m='3'>2323</sms>
<email>abc@gmail.com</email>
<email m='3'>xyz@outlook.com</email></row>

How can I use Xpath and XQuery in Oracle DB to have the following expected output in only one row:如何在 Oracle DB 中使用 Xpath 和 XQuery 以仅在一行中获得以下预期输出:

Name姓名 Phone电话 Sms短信 Email电子邮件
Martin H马丁 H 1111#2222# 1111#2222# #1212#2323 #1212#2323 abc@gmail.com##xyz@outlook.com abc@gmail.com##xyz@outlook.com

Basically, a '#' is used to separate values and any missing tag of any group from XML above is returned as a null value.基本上,'#' 用于分隔值,并且上述 XML 中任何组的任何缺失标记都将作为空值返回。

Any help will be much appreciated.任何帮助都感激不尽。 Thanks!谢谢!

Using XMLTABLE to parse your XML into columns, you can then use the string-join operator when defining the path to perform a similar functionality to LISTAGG .使用XMLTABLE将您的 XML 解析为列,然后您可以在定义路径时使用string-join运算符来执行与LISTAGG类似的功能。

WITH
    example_table (xml_clob)
    AS
        (SELECT EMPTY_CLOB () || '<row id=''123456'' xml:space=''preserve''>
    <name>Martin H</name>
    <phone>1111</phone>
    <phone m=''2''>2222</phone>
    <phone m=''3''></phone>
    <sms m=''2''>1212</sms>
    <sms m=''3''>2323</sms>
    <email>abc@gmail.com</email>
    <email m=''3''>xyz@outlook.com</email>
</row>' FROM DUAL)
SELECT xt.*
  FROM example_table  et
       CROSS JOIN
       XMLTABLE (
           'row'
           PASSING xmltype (et.xml_clob)
           COLUMNS name VARCHAR2 (100)
                       PATH 'name',
                   phone VARCHAR2 (100)
                       PATH 'string-join(phone,"#")',
                   sms VARCHAR2 (100)
                       PATH 'string-join(sms,"#")',
                   email VARCHAR2 (100)
                       PATH 'string-join(email,"#")') xt;

NAME        PHONE         SMS          EMAIL
___________ _____________ ____________ ________________________________
Martin H    1111#2222#    1212#2323    abc@gmail.com#xyz@outlook.com

Update更新

After reading kfinity's comment and understanding the problem a bit clearer, the problem can still be solved using XMLTABLE , then CASE statements to contatenate the values together for the desired result.在阅读 kfinity 的评论并更清楚地理解问题后,仍然可以使用XMLTABLE解决问题,然后使用CASE语句将值连接在一起以获得所需的结果。

WITH
    example_table (xml_clob)
    AS
        (SELECT EMPTY_CLOB () || '<row id=''123456'' xml:space=''preserve''>
    <name>Martin H</name>
    <phone>1111</phone>
    <phone m=''2''>2222</phone>
    <phone m=''3''></phone>
    <sms m=''2''>1212</sms>
    <sms m=''3''>2323</sms>
    <email>abc@gmail.com</email>
    <email m=''3''>xyz@outlook.com</email>
</row>' FROM DUAL)
SELECT xt.name,
          CASE
              WHEN phone1_mtag IS NULL AND phone1 IS NOT NULL THEN phone1
              WHEN phone2_mtag IS NULL AND phone2 IS NOT NULL THEN phone2
              WHEN phone3_mtag IS NULL AND phone3 IS NOT NULL THEN phone3
          END
       || '#'
       || CASE
              WHEN phone1_mtag = '2' AND phone1 IS NOT NULL THEN phone1
              WHEN phone2_mtag = '2' AND phone2 IS NOT NULL THEN phone2
              WHEN phone3_mtag = '2' AND phone3 IS NOT NULL THEN phone3
          END
       || '#'
       || CASE
              WHEN phone1_mtag = '3' AND phone1 IS NOT NULL THEN phone1
              WHEN phone2_mtag = '3' AND phone2 IS NOT NULL THEN phone2
              WHEN phone3_mtag = '3' AND phone3 IS NOT NULL THEN phone3
          END    AS phone,
          CASE
              WHEN sms1_mtag IS NULL AND sms1 IS NOT NULL THEN sms1
              WHEN sms2_mtag IS NULL AND sms2 IS NOT NULL THEN sms2
              WHEN sms3_mtag IS NULL AND sms3 IS NOT NULL THEN sms3
          END
       || '#'
       || CASE
              WHEN sms1_mtag = '2' AND sms1 IS NOT NULL THEN sms1
              WHEN sms2_mtag = '2' AND sms2 IS NOT NULL THEN sms2
              WHEN sms3_mtag = '2' AND sms3 IS NOT NULL THEN sms3
          END
       || '#'
       || CASE
              WHEN sms1_mtag = '3' AND sms1 IS NOT NULL THEN sms1
              WHEN sms2_mtag = '3' AND sms2 IS NOT NULL THEN sms2
              WHEN sms3_mtag = '3' AND sms3 IS NOT NULL THEN sms3
          END    AS sms,
          CASE
              WHEN email1_mtag IS NULL AND email1 IS NOT NULL THEN email1
              WHEN email2_mtag IS NULL AND email2 IS NOT NULL THEN email2
              WHEN email3_mtag IS NULL AND email3 IS NOT NULL THEN email3
          END
       || '#'
       || CASE
              WHEN email1_mtag = '2' AND email1 IS NOT NULL THEN email1
              WHEN email2_mtag = '2' AND email2 IS NOT NULL THEN email2
              WHEN email3_mtag = '2' AND email3 IS NOT NULL THEN email3
          END
       || '#'
       || CASE
              WHEN email1_mtag = '3' AND email1 IS NOT NULL THEN email1
              WHEN email2_mtag = '3' AND email2 IS NOT NULL THEN email2
              WHEN email3_mtag = '3' AND email3 IS NOT NULL THEN email3
          END    AS email
  FROM example_table  et
       CROSS JOIN XMLTABLE ('row'
                            PASSING xmltype (et.xml_clob)
                            COLUMNS name VARCHAR2 (100) PATH 'name',
                                    phone1 VARCHAR2 (100) PATH 'phone[1]',
                                    phone1_mtag VARCHAR2 (100) PATH 'phone[1]/@m',
                                    phone2 VARCHAR2 (100) PATH 'phone[2]',
                                    phone2_mtag VARCHAR2 (100) PATH 'phone[2]/@m',
                                    phone3 VARCHAR2 (100) PATH 'phone[3]',
                                    phone3_mtag VARCHAR2 (100) PATH 'phone[3]/@m',
                                    sms1 VARCHAR2 (100) PATH 'sms[1]',
                                    sms1_mtag VARCHAR2 (100) PATH 'sms[1]/@m',
                                    sms2 VARCHAR2 (100) PATH 'sms[2]',
                                    sms2_mtag VARCHAR2 (100) PATH 'sms[2]/@m',
                                    sms3 VARCHAR2 (100) PATH 'sms[3]',
                                    sms3_mtag VARCHAR2 (100) PATH 'sms[3]/@m',
                                    email1 VARCHAR2 (100) PATH 'email[1]',
                                    email1_mtag VARCHAR2 (100) PATH 'email[1]/@m',
                                    email2 VARCHAR2 (100) PATH 'email[2]',
                                    email2_mtag VARCHAR2 (100) PATH 'email[2]/@m',
                                    email3 VARCHAR2 (100) PATH 'email[3]',
                                    email3_mtag VARCHAR2 (100) PATH 'email[3]/@m') xt;
NAME        PHONE         SMS           EMAIL
___________ _____________ _____________ _________________________________
Martin H    1111#2222#    #1212#2323    abc@gmail.com##xyz@outlook.com

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM