Pig:使用嵌套对象加载 xml

Posted

技术标签:

【中文标题】Pig:使用嵌套对象加载 xml【英文标题】:Pig: Load xml with nested objects 【发布时间】:2014-04-23 14:21:46 【问题描述】:

以下 xml 包含类别和产品。我可以成功加载类别,但我不能加载产品,因为其中有一个嵌套的颜色对象。我如何在猪中处理这个 xml?

xml:

<?xml version="1.0" encoding="UTF-8" ?>
<Feed xmlns="http://www.xx.com/PRR/ProductFeed/1.0"
              name="xx"
              incremental="false"
              extractDate="2014-04-22T11:00:00.000000">
 <Categories>
  <Category>
   <ExternalId>2_5</ExternalId>
   <ParentExternalId></ParentExternalId>
   <Name>Baby</Name>
   <CategoryPageUrl>http://www.xx.com/en-US/Clearance/Baby-0-3yrs-Clothing.html</CategoryPageUrl>
  </Category>
  <Category>
   <ExternalId>2_3</ExternalId>
   <ParentExternalId></ParentExternalId>
   <Name>Boys 1½-12yrs</Name>
   <CategoryPageUrl>http://www.xx.com/en-US/Clearance/Boys-1H-12yrs-Clothing.html</CategoryPageUrl>
  </Category>
 </Categories>
 <Products>
  <Product>
   <ExternalId>78094</ExternalId>
   <Name>Sleep Bag</Name>
   <Description>A cover they can't throw off in the night. Pure cotton with one of our uniquely lovely prints. In its own gift box. An ultra thoughtful, luxurious present.</Description>
   <Brand>xx</Brand>
   <CategoryExternalId>1_5_1</CategoryExternalId>
   <ProductPageUrl>http://www.xx.com/en-US/Baby-0-3yrs-Accessories/78094/Baby-0-3yrs-Sleep-Bag.html</ProductPageUrl>
   <ImageUrl>http://www.xx.com/productimages/productThumb160x207/14USPR_78094_MUL.jpg</ImageUrl>
   <SwatchImageUrl>http://www.xx.com/productimages/grsw/14USPR_78094_MUL_s.jpg</SwatchImageUrl>
   <Price>54.0000</Price>
   <Wasprice>54.0000</Wasprice>
   <ManufacturerPartNumber></ManufacturerPartNumber>
   <EAN></EAN>
   <Colours>
    <Variation>
     <Tier2>MUL</Tier2>
     <Tier2Descr>Multi Elephant Party</Tier2Descr>
     <Tier2Url>http://www.xx.com/en-US/Baby-0-3yrs-Accessories/78094-MUL/Baby-0-3yrs-Multi-Elephant-Party-Sleep-Bag.html</Tier2Url>
     <Tier2ImageUrl>http://www.xx.com/productimages/productThumb160x207/14USPR_78094_MUL.jpg</Tier2ImageUrl>
     <Tier3>03 06</Tier3>
     <Tier3Descr>3-6m</Tier3Descr>
     <StockStatus>-2</StockStatus>
     <SwatchUrl>http://www.xx.com/productimages/grsw/14USPR_78094_MUL_s.jpg</SwatchUrl>
    </Variation>
    <Variation>
     <Tier2>MUL</Tier2>
     <Tier2Descr>Multi Elephant Party</Tier2Descr>
     <Tier2Url>http://www.xx.com/en-US/Baby-0-3yrs-Accessories/78094-MUL/Baby-0-3yrs-Multi-Elephant-Party-Sleep-Bag.html</Tier2Url>
     <Tier2ImageUrl>http://www.xx.com/productimages/productThumb160x207/14USPR_78094_MUL.jpg</Tier2ImageUrl>
     <Tier3>06 18</Tier3>
     <Tier3Descr>6-18m</Tier3Descr>
     <StockStatus>-2</StockStatus>
     <SwatchUrl>http://www.xx.com/productimages/grsw/14USPR_78094_MUL_s.jpg</SwatchUrl>
    </Variation>
   </Colours>
  </Product>
 </Products>
</Feed>

我用于分类的猪脚本:

REGISTER 'lib/pig/piggybank.jar'

raw = load '$INPUT_FEED' using org.apache.pig.piggybank.storage.XMLLoader('Category') 
    as (x:chararray);

raw_category = foreach raw GENERATE FLATTEN(REGEX_EXTRACT_ALL(x,
    '<Category>\\n\\s*<ExternalId>(.*)</ExternalId>\\n\\s*<ParentExternalId>(.*)</ParentExternalId>\\n\\s*<Name>(.*)</Name>\\n\\s*<CategoryPageUrl>(.*)</CategoryPageUrl>\\n\\s*</Category>'))
    as (external_id:chararray, parent_external_id:chararray, name:chararray, categorypageurl:chararray);

这工作正常,但我如何加载产品?最好将负载类别和产品放在一个负载语句中,但更糟糕的情况是两个部分也很好。

提前致谢

更新:

最后我也能够定义嵌套字段,但只有在颜色下只有一种变化时才有效。如果我使用上面的 xml,它会返回一个空行。如果我删除颜色下的变体(因此只剩下一个变体),那么它会正确返回原始数据。

任何想法我做错了什么?我希望从上面的 xml 中取回两行。

raw = load '$INPUT_FEED' using org.apache.pig.piggybank.storage.XMLLoader('Product') 
    as (x:chararray);

raw_product = foreach raw GENERATE FLATTEN(REGEX_EXTRACT_ALL(x,
    '<Product>\\n\\s*<ExternalId>(.*)</ExternalId>\\n\\s*<Name>(.*)</Name>\\n\\s*<Description>(.*)</Description>\\n\\s*<Brand>(.*)</Brand>\\n\\s*<CategoryExternalId>(.*)</CategoryExternalId>\\n\\s*<ProductPageUrl>(.*)</ProductPageUrl>\\n\\s*<ImageUrl>(.*)</ImageUrl>\\n\\s*<SwatchImageUrl>(.*)</SwatchImageUrl>\\n\\s*<Price>(.*)</Price>\\n\\s*<Wasprice>(.*)</Wasprice>\\n\\s*<ManufacturerPartNumber>(.*)</ManufacturerPartNumber>\\n\\s*<EAN>(.*)</EAN>\\n\\s*<Colours>\\n\\s*<Variation>\\n\\s*<Tier2>(.*)</Tier2>\\n\\s*<Tier2Descr>(.*)</Tier2Descr>\\n\\s*<Tier2Url>(.*)</Tier2Url>\\n\\s*<Tier2ImageUrl>(.*)</Tier2ImageUrl>\\n\\s*<Tier3>(.*)</Tier3>\\n\\s*<Tier3Descr>(.*)</Tier3Descr>\\n\\s*<StockStatus>(.*)</StockStatus>\\n\\s*<SwatchUrl>(.*)</SwatchUrl>\\n\\s*</Variation>\\n\\s*</Colours>\\n\\s*</Product>')) 
    as (external_id:chararray, name:chararray, description:chararray, brand:chararray, category_external_id:chararray, product_page_url:chararray, image_url:chararray, swatch_image_url:chararray, price:float, wasprice:float, manufacturer_part_number:chararray, ean:chararray, tier2:chararray, tier2desc:chararray, tier2url:chararray, tier2imageurl:chararray, tier3:chararray, tier3desc:chararray, stockstatus:chararray, swatchurl:chararray);

【问题讨论】:

你是说如果你对产品做同样的事情作为另一个负载语句它将不起作用。 raw = 使用 org.apache.pig.piggybank.storage.XMLLoader('Product') 作为 (x:chararray) 加载'$INPUT_FEED'; 是的,因为它也有颜色嵌套数组,我不知道如何定义这些字段。 现在我也可以定义嵌套字段,但仅在嵌套数组只有一个元素时才有效,如果多于一个则返回空行。 【参考方案1】:

因此,如果 xml 包含命名空间,那么通过 pig 处理 xml 会出现很大问题。piggybank 的 Xpath 尚不支持此功能(我使用的是最新版本 piggybank0.14)。此外,嵌套路径遍历目前不可行(例如 - /book/author/name)返回空白值。

他们正在 pig0.15 中开发一个功能:https://issues.apache.org/jira/browse/PIG-4355

这里他们引入了检查命名空间和 XpathAll UDF 的条件,解决了上述问题,但此版本尚未发布。虽然在https://github.com/apache/pig/pull/14 上提供了补丁。

另一种选择是,您可以使用 python 或任何其他您熟悉的语言添加自己的 UDF,以解析您的特定用例。

【讨论】:

以上是关于Pig:使用嵌套对象加载 xml的主要内容,如果未能解决你的问题,请参考以下文章

使用 Pig 在 XPath 中进行嵌套解析

如何在 pig 中读取带有嵌套节点的 XML 文件

无法使用 Pig 中的 Elephant Bird 访问带有包和元组的嵌套 JSON

解析 PIG-XML 时出错

我可以使用 Pig Latin 中的嵌套 FOREACH 语句生成嵌套包吗?

用大象鸟加载嵌套的json后如何查询它