使用 Xpath 将 XML 节点提取到 Hive 表中
Posted
技术标签:
【中文标题】使用 Xpath 将 XML 节点提取到 Hive 表中【英文标题】:Extracting XML nodes into Hive table using Xpath 【发布时间】:2017-07-14 23:17:13 【问题描述】:我们有一个 Hive 表,其中一个字符串列包含 XML。为简化起见,假设该表为:
DataTable
key: string
xml: string
并且xml格式为:
<xml>
<entity>
<property type="alpha">123</property>
<property type="beta">abc</property>
<property type="delta">...</property>
</entity>
<entity>
<property type="alpha">321</property>
<property type="beta">cba</property>
<property type="delta">---</property>
</entity>
</xml>
有 0..N 个实体节点。
我想将此数据转换为具有以下格式的新 Hive 表:
TransformedTable
key: string
alpha: string
beta: string
delta: string
但我觉得很难。我对 Hive 很陌生,但我认为这样的事情应该就在它的小巷里。
以下问题相关:
Parsing a nested XML string from a Hive table using PIG Parse repeating XML tags in Hive但没有答案。而这个问题有一个相关的答案:
Exception while using lateral view in Hive但我认为在这种情况下我不能使用 xml SerDe。通过这项研究,我尝试过这样的事情:
select key,
xpath(xml, 'xml/entity/property[@type="alpha"]/text()')) as alpha,
xpath(xml, 'xml/entity/property[@type="beta"]/text()')) as beta,
xpath(xml, 'xml/entity/property[@type="delta"]/text()')) as delta
from DataTable
但这会导致:
key1 ["123", "321"] ["abc", "cba"] ["...", "---"]
key2 ["123", "321"] ["abc", "cba"] ["...", "---"]
而不是我真正想要的:
key1 123 abc ...
key1 321 cba ---
key2 123 abc ...
key2 321 cba ---
感谢您花时间阅读本文,如果您能给我任何建议,我将不胜感激!
【问题讨论】:
【参考方案1】:可以使用LATERAL VIEW
与explode
等表格生成函数将基于数组的数据“加入”到关系中。在这种情况下,另一个复杂情况是我们需要 3 次单独出现的 LATERAL VIEW
对应于 alpha
beta
和 delta
数组,这会在结果集中产生完整的笛卡尔积的风险;每个 alpha/beta/delta 排列都会生成一个单独的行。
为了避免笛卡尔积,我们可以使用函数的变体posexplode
,它会从原始数组生成数字索引和数据值。然后,我们可以使用过滤条件来确保我们只查看原始数组中按位置匹配的行。
查询
WITH DataTable AS (
SELECT 'key1' AS key, '<xml><entity><property type="alpha">123</property><property type="beta">abc</property><property type="delta">...</property></entity><entity><property type="alpha">321</property><property type="beta">cba</property><property type="delta">---</property></entity></xml>' AS xml UNION ALL
SELECT 'key2' AS key, '<xml><entity><property type="alpha">123</property><property type="beta">abc</property><property type="delta">...</property></entity><entity><property type="alpha">321</property><property type="beta">cba</property><property type="delta">---</property></entity></xml>' AS xml
)
SELECT
key,
alpha,
beta,
delta
FROM DataTable
LATERAL VIEW posexplode(xpath(xml, 'xml/entity/property[@type="alpha"]/text()')) xml_alpha AS pos_alpha, alpha
LATERAL VIEW posexplode(xpath(xml, 'xml/entity/property[@type="beta"]/text()')) xml_beta AS pos_beta, beta
LATERAL VIEW posexplode(xpath(xml, 'xml/entity/property[@type="delta"]/text()')) xml_delta AS pos_delta, delta
WHERE pos_alpha = pos_beta
AND pos_beta = pos_delta
;
结果集
key alpha beta delta
0 key1 123 abc ...
1 key1 321 cba ---
2 key2 123 abc ...
3 key2 321 cba ---
如果需要进一步自定义,那么您可以考虑编写自己的自定义 UDTF,以完全按照您的需要生成行。
【讨论】:
谢谢克里斯。您的回答既正确又具有教育意义。非常有帮助!现在,我正在努力尝试以某种方式组合一个 OUTER 视图,因为并非每个实体都具有例如“beta”属性,在这种情况下,我希望 beta 列中有一个 NULL。我会再玩一些,如果我想不通,我会发布一个不同的问题。再次感谢。 @Ckratide ,很高兴听到这有帮助!听起来您可能正走在需要更多自定义逻辑的道路上。我编辑了答案,说您可能要考虑编写自己的自定义 UDTF。 cwiki.apache.org/confluence/display/Hive/DeveloperGuide+UDTF以上是关于使用 Xpath 将 XML 节点提取到 Hive 表中的主要内容,如果未能解决你的问题,请参考以下文章