Reputation: 45
I am new to XPath. I need help with the XPath needed to extract the Book's Title and Authors towards the end of this XML. I tried the following C# code with no success. I just need to list the Book's Title and Authors under . Looks like the xmlns namespace affects my XPaths. My code works if I manually remove the xmlns. So, either I modify the XPath to account for this namespace or figure out a way to remove that attribute from the XML. Please advise.
Here is the C# code:
XmlNodeList nodes = XML.DocumentElement.SelectNodes("//Title");
foreach (XmlNode node in nodes)
{
Console.WriteLn(node.Name + " = " + node.InnerText); }
}
Here is the XML:
<?xml version="1.0"?>
<ItemSearchResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
<OperationRequest>
<RequestId>xxxxx</RequestId>
<Arguments>
<Argument Name="Condition" Value="All"></Argument>
<Argument Name="ResponseGroup" Value="Small,Images"></Argument>
<Argument Name="SearchIndex" Value="Books"></Argument>
</Arguments>
<RequestProcessingTime>0.0735170000000000</RequestProcessingTime>
</OperationRequest>
<Items>
<Request>
<IsValid>True</IsValid>
<ItemSearchRequest>
<Condition>All</Condition>
<Keywords>Perl</Keywords>
<ResponseGroup>Small</ResponseGroup>
<ResponseGroup>Images</ResponseGroup>
<SearchIndex>Books</SearchIndex>
</ItemSearchRequest>
</Request>
<TotalResults>3761</TotalResults>
<TotalPages>377</TotalPages>
<MoreSearchResultsUrl>http://www.amazon.com/gp/redirect.html?camp=2025&creative=386001&location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Fsearch%3Fkeywords%3DPerl%26url%3Dsearch-alias%253Dstripbooks&linkCode=xm2&tag=geo01d-20&SubscriptionId=AKIAJJBQEKP2X72RQ6XA</MoreSearchResultsUrl>
<Item>
<ASIN>1449303587</ASIN>
<DetailPageURL>http://www.amazon.com/Learning-Perl-Randal-L-Schwartz/dp/1449303587%3FSubscriptionId%3DAKIAJJBQEKP2X72RQ6XA%26tag%3Dgeo01d-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1449303587</DetailPageURL>
<ItemLinks>
<ItemLink>
<Description>Technical Details</Description>
<URL>http://www.amazon.com/Learning-Perl-Randal-L-Schwartz/dp/tech-data/1449303587%3FSubscriptionId%3DAKIAJJBQEKP2X72RQ6XA%26tag%3Dgeo01d-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D1449303587</URL>
</ItemLink>
<ItemLink>
<Description>All Offers</Description>
<URL>http://www.amazon.com/gp/offer-listing/1449303587%3FSubscriptionId%3DAKIAJJBQEKP2X72RQ6XA%26tag%3Dgeo01d-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D1449303587</URL>
</ItemLink>
</ItemLinks>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51kTNE8aIXL._SL75_.jpg</URL>
<Height Units="pixels">75</Height>
<Width Units="pixels">58</Width>
</SmallImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51kTNE8aIXL._SL160_.jpg</URL>
<Height Units="pixels">160</Height>
<Width Units="pixels">123</Width>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51kTNE8aIXL.jpg</URL>
<Height Units="pixels">500</Height>
<Width Units="pixels">385</Width>
</LargeImage>
<ImageSets>
<ImageSet Category="primary">
<SwatchImage>
<URL>http://ecx.images-amazon.com/images/I/51kTNE8aIXL._SL30_.jpg</URL>
<Height Units="pixels">30</Height>
<Width Units="pixels">23</Width>
</SwatchImage>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51kTNE8aIXL._SL75_.jpg</URL>
<Height Units="pixels">75</Height>
<Width Units="pixels">58</Width>
</SmallImage>
</ImageSet>
</ImageSets>
<ItemAttributes>
<Author>Randal L. Schwartz</Author>
<Author>brian d foy</Author>
<Author>Tom Phoenix</Author>
<Manufacturer>O'Reilly Media</Manufacturer>
<ProductGroup>Book</ProductGroup>
<Title>Learning Perl</Title>
</ItemAttributes>
</Item>
</Items>
</ItemSearchResponse>
Upvotes: 1
Views: 146
Reputation: 45
I finally figured out an answer to my question. I simply removed the namespace which overly complicated my XPath's. The C# code below works. PrintKeyValue simply prints Key = Value.
XML = new XmlDocument();
using (XmlTextReader reader = new XmlTextReader("C:\\Path\\File.xml"))
{
reader.Namespaces = false;
XML.Load(reader);
}
XmlNodeList items = XML.DocumentElement.SelectNodes("//Item");
foreach (XmlNode item in items)
{
PrintKeyValue("ISBN10", item["ASIN"].InnerText);
XmlNode attrib = item.SelectSingleNode(".//ItemAttributes");
PrintKeyValue("Title", attrib["Title"].InnerText);
XmlNodeList authors = attrib.SelectNodes(".//Author");
StringBuilder sb = new StringBuilder();
int count = 0;
foreach (XmlNode author in authors)
{
count++;
if (count > 1) { sb.Append(", "); }
sb.Append(author.InnerText);
}
PrintKeyValue("Authors", sb.ToString());
}
Upvotes: 0
Reputation: 163585
The XPath needs to be "//p:Title", and you need to tell the XPath processor that the namespace prefix "p" stands for the namespace "http://webservices.amazon.com/AWSECommerceService/2011-08-01". The way you establish namespace bindings depends on the API of your chosen XPath processor. For C# you can find an explanation of how to do it here (or in many, many other previous StackOverflow answers):
Xml-SelectNodes with default-namespace via XmlNamespaceManager not working as expected
Upvotes: 0
Reputation: 2222
You can do this with Linq-to-XML:
XDocument xmlDoc = XDocument.Parse(xmlString);
var q = from el in xmlDoc.Descendants()
.Where(x => x.Name.LocalName == "Title" || x.Name.LocalName == "Author")
select el;
foreach (var xElement in q)
{
Debug.WriteLine(xElement.Name.LocalName + " : " + xElement.Value);
}
The Output:
Author : Randal L. Schwartz
Author : brian d foy
Author : Tom Phoenix
Title : Learning Perl
Upvotes: 1