解析雪花中的嵌套 XML

时间:2021-01-25 14:28:47

标签: xml xml-parsing snowflake-cloud-data-platform

我有以下 XML 文件,我已将其作为 VARIANT 类型导入到 Snowflake 表中。

<xyz>
  <Header>
    <VersionInfo>
      <Version>2.1.0</Version>
      <Notes>Draft report v1</Notes>
    </VersionInfo>
    <Environment>Env1</Environment>
    <SubID>5787685</SubID>
  </Header>
  <Items>
    <NEWT>
      <ItemNo>12345</ItemNo>
      <ItemBody>
        <RptDt>2021-01-19T06:54:42.483Z</RptDt>
        <RptEnt>
          <Entity>123</Entity>
        </RptEnt>
        <IsVerified>FALSE</IsVerified>
      </ItemBody>
    </NEWT>
  </Items>
  <Items>
    <NEWT>
      <ItemNo>23456</ItemNo>
      <ItemBody>
        <RptDt>2021-01-19T06:54:42.483Z</RptDt>
        <RptEnt>
          <Entity>2346</Entity>
        </RptEnt>
        <IsVerified>TRUE</IsVerified>
      </ItemBody>
    </NEWT>
  </Items>
 </xyz>

我正在尝试解析 XML 并从数据中生成两个不同的雪花表。第一个查询有效,并从该部分提取数据。 这是查询:

  -- get header and version
SELECT 
  XMLGET(Header.value, 'Environment'):"$"::string  Environment,
  XMLGET(Header.value, 'SubID'):"$"::string  SubID,
  XMLGET(Version.value, 'Version'):"$"::string  Version,
  XMLGET(Version.value, 'Notes'):"$"::string  Notes
FROM 
   MyTable  ,
  LATERAL FLATTEN(GET(xml_import, '$')) Header ,
  LATERAL FLATTEN(GET(Header.value, '$')) Version 
WHERE 
  GET(Header.value, '@') = 'Header'
  and GET(Version.value, '@') = 'VersionInfo';  

下面是想要的结果:

ENVIRONMENT     SUBID       VERSION     NOTES
Env1            5787685     2.1.0       Draft report v1

对于下一部分,我在解析该部分的所有级别时遇到问题。所需的结果将是一个表格,其中每个表格都有一行数据,来自 XML 文件。

ItemNo  RptDt               RptEnt      IsVerified
12345   2021-01-19T06:54:42.483Z    123         FALSE
23456   2021-01-19T06:54:42.483Z    2346        TRUE

我尝试编写以下 SQL,但我很难过滤行和导航嵌套级别。

 -- get items and reports
select 
XMLGET(flt1.value, 'RptDt'):"$"::string  RptDate,
XMLGET(flt1.value, 'IsVerified'):"$"::string  IsVerified

FROM 
  MyTable src1,
       lateral flatten(to_array(xmlget(xmlget(src1.xml_import, 'Items'), 'NEWT'):"$")) flt1

我确信有一种更有效的方法来查询这些数据并将其转换为表格格式。任何人都可以建议如何遍历多个级别和多个重复,而忽略

1 个答案:

答案 0 :(得分:1)

我正在寻找缩短此代码的方法 - 但它适用于您的示例:

select xmlget(emp.value:"$", 'ItemNo'):"$" ItemNo
, xmlget(xmlget(emp.value:"$", 'ItemBody'), 'RptDt'):"$"::timestamp RptDt
, xmlget(xmlget(emp.value:"$", 'ItemBody'), 'RptEnt'):"$":"$" RptEnt
, xmlget(xmlget(emp.value:"$", 'ItemBody'), 'IsVerified'):"$"::boolean IsVerified
from onexml
    ,  lateral flatten(onexml.xml_import:"$") emp
where get(emp.value, '@')='Items';

enter image description here

示例数据:

create temp table onexml as
select parse_xml('<xyz>
  <Header>
    <VersionInfo>
      <Version>2.1.0</Version>
      <Notes>Draft report v1</Notes>
    </VersionInfo>
    <Environment>Env1</Environment>
    <SubID>5787685</SubID>
  </Header>
  <Items>
    <NEWT>
      <ItemNo>12345</ItemNo>
      <ItemBody>
        <RptDt>2021-01-19T06:54:42.483Z</RptDt>
        <RptEnt>
          <Entity>123</Entity>
        </RptEnt>
        <IsVerified>FALSE</IsVerified>
      </ItemBody>
    </NEWT>
  </Items>
  <Items>
    <NEWT>
      <ItemNo>23456</ItemNo>
      <ItemBody>
        <RptDt>2021-01-19T06:54:42.483Z</RptDt>
        <RptEnt>
          <Entity>2346</Entity>
        </RptEnt>
        <IsVerified>TRUE</IsVerified>
      </ItemBody>
    </NEWT>
  </Items>
 </xyz>') xml_import;