Hadoop Hive XPaths只返回数组的一部分

时间:2017-07-27 10:49:40

标签: xml hadoop xpath xquery

我正在使用Hadoop Hive并尝试处理XML文件。该文件如下所示:

<asds4_0:SASDS>
<stl15:GetRS>
    <stl15:RS>
        <stl15:ORES>
            <stl15:ORE>
                <stl15:AccF>
                    <stl15:Transaction>
                        <stl15:Status>Hold</stl15:Status>
                    </stl15:Transaction>
                </stl15:AccF>
            </stl15:ORE>
            <stl15:ORE>
                <stl15:AccF>
                    <stl15:Transaction>
                        <stl15:Status>Active</stl15:Status>
                    </stl15:Transaction>
                </stl15:AccF>
            </stl15:ORE>
        </stl15:ORES>
    </stl15:RS>
</stl15:GetRS>
</asds4_0:SASDS>

我用来检索状态的xpath是:

SELECT
Status
FROM scenario1
LATERAL VIEW explode(xpath(cast(body as string),"//*[local-name()='SASDS']//*[local-name()='GetRS']//*[local-name()='RS']//*[local-name()='ORES']//*[local-name()='ORE']//*[local-name()='AccF']//*[local-name()='Transaction']//*[local-name()='Status']/text()")) adTable as Status

此xpath返回Active和Hold状态。问题是我只想检索Active状态。  我尝试使用这样的东西[[local-name()='Status'] ='Active'](就像它显示在这里https://www.w3schools.com/xml/xpath_syntax.asp)我仍然得到两个记录Hold和Active。

我不想在sql中使用WHERE Status ='Active',因为当我将其与其他字段组合时,它不会返回所需的行。

2 个答案:

答案 0 :(得分:0)

首先,您使用类似

的构造是否有任何具体原因
*[local-name()='SASDS']

到处都是?

等同于(但不太可读)
*:SASDS

此外,您在任何地方都使用//*,它返回并搜索所有后代元素。但是考虑到你的XML结构,你通常只想访问直接的孩子,因此使用/搜索孩子时再次更具可读性(也更快)。

所以,更好的是:

*:SASDS/*:GetRS/*:RS/*:ORES/*:ORE/*:AccF/*:Transaction/*:Status[. = "Active"]/text()

答案 1 :(得分:0)

我喜欢Dirkk的解决方案但是,正如您可能已经发现的那样,它不会为您工作。 Hive中内置XML支持的许多限制之一是它基于XPath 1.0。

但是,您可以将他的解决方案与Oracle XML Extensions for Hive一起使用: http://docs.oracle.com/bigdata/bda49/BDCUG/oxh_hive.htm#BDCUG691

它是Oracle XQuery for Hadoop的一部分,可以在这里下载: http://www.oracle.com/technetwork/database/database-technologies/bdc/big-data-connectors/downloads/index.html

示例:

  SELECT xml_query_as_string(
    "*:SASDS/*:GetRS/*:RS/*:ORES/*:ORE/*:AccF/*:Transaction/*:Status[. = 'Active']", 
    body
  ) 
  FROM scenario1;

将返回:&#34;有效&#34;

还有一个表函数:

  SELECT t.status
  FROM scenario1 LATERAL VIEW xml_table(
    '*:SASDS/*:GetRS/*:RS/*:ORES/*:ORE/*:AccF/*:Transaction', 
    body, 
    struct ('*:Status')
  ) t as status
  WHERE t.status = 'Active';

如果你想抛弃通配符,那么很好的命名空间支持:

SELECT t.status
FROM scenario1 LATERAL VIEW xml_table(
  struct(
    'stl15', 'http://example.org/ns1',
    'asds4_0', 'http://example.org/ns2'
  ),
  'asds4_0:SASDS/stl15:GetRS/stl15:RS/stl15:ORES/stl15:ORE/stl15:AccF/stl15:Transaction', 
  body, 
  struct ('stl15:Status')
) t as status
WHERE t.status = 'Active';