Reputation: 4615
I'm using the code below to retreive the content of the ns2:Title tag from the XML shown below.
What I have so far:
results = Nokogiri::XML(search_results)
p results.xpath '//ns2:Title', 'ns2': 'http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd'
It works, but I don't like having to mention the ns2 namespace URL explicitly when it's already in the XML document. But I can't seem to retrieve it from the Products tag. I've tried variants of p results.css('Products').attr('xmlns:n2')
but I can't get that work work, it just returns nil. How can I get the xmlns:n2 attribute value of the Products
tag?
My (simplified for brevity) XML:
<?xml version="1.0"?>
<GetMatchingProductForIdResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMatchingProductForIdResult Id="028023810000" IdType="UPC" status="Success">
<Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
<Product>
<AttributeSets>
<ns2:ItemAttributes xml:lang="en-US">
<ns2:Studio>WECO Electrical Connectors Inc</ns2:Studio>
<ns2:Title>Weco Wonder Shell Natural Minerals (3 Pack), Small</ns2:Title>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships>
<VariationParent>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>B077HQHBQ6</ASIN>
</MarketplaceASIN>
</Identifiers>
</VariationParent>
</Relationships>
<SalesRankings>
<SalesRank>
<ProductCategoryId>pet_products_display_on_website</ProductCategoryId>
<Rank>14863</Rank>
</SalesRank>
</SalesRankings>
</Product>
</Products>
</GetMatchingProductForIdResult>
</GetMatchingProductForIdResponse>
Upvotes: 0
Views: 628
Reputation: 29598
css
and xpath
will return a NodeSet
(think Enumerable#select
) but you want the actual Element
itself.
For this nokogiri
provides the at_
prefixed methods, at_css
and at_xpath
, which will return the first matching Element
. The implementation is very simple
css(*args).first
So in order to get the namespace you are looking for either of the following will work and the are both identical in nature
results.css('Products').first.namespaces['xmlns:ns2']
#=> "http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd"
results.at_css('Products').namespaces['xmlns:ns2']
#=> "http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd"
However if your only target is the "ns2:Title" Elements then
results.xpath("//*[name() = 'ns2:Title']").text
#=> "Weco Wonder Shell Natural Minerals (3 Pack), Small"
Additionally if you just want any "Title" attributes and the name space is not necessary important then
results.xpath("//*[local-name() ='Title']").text
#=> "Weco Wonder Shell Natural Minerals (3 Pack), Small"
Upvotes: 1