Что такое XPath для этого XML с пространством имен

Я новичок в XPath. Мне нужна помощь с XPath, необходимым для извлечения названия книги и авторов ближе к концу этого XML. Я безуспешно пробовал следующий код С#. Мне просто нужно указать название книги и авторов в разделе . Похоже, пространство имен xmlns влияет на мои XPath. Мой код работает, если я вручную удалю файл xmlns. Итак, либо я изменяю XPath для учета этого пространства имен, либо нахожу способ удалить этот атрибут из XML. Пожалуйста, порекомендуйте.

Вот код С#:

XmlNodeList nodes = XML.DocumentElement.SelectNodes("//Title");
foreach (XmlNode node in nodes)
{
Console.WriteLn(node.Name + " = " + node.InnerText); }
}

Вот 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&amp;creative=386001&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Fsearch%3Fkeywords%3DPerl%26url%3Dsearch-alias%253Dstripbooks&amp;linkCode=xm2&amp;tag=geo01d-20&amp;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>

person Aladdin Nassar    schedule 30.11.2014    source источник


Ответы (3)


XPath должен быть "//p:Title", и вам нужно сообщить обработчику XPath, что префикс пространства имен "p" означает пространство имен "http://webservices.amazon.com/AWSECommerceService/2011-08-01". То, как вы устанавливаете привязки пространств имен, зависит от API выбранного вами процессора XPath. Для С# вы можете найти объяснение того, как это сделать здесь (или во многих других предыдущих ответах StackOverflow):

Xml-SelectNodes с пространством имен по умолчанию через XmlNamespaceManager not работает как положено

person Michael Kay    schedule 01.12.2014
comment
Большое спасибо, Майкл. Мало того, что пространство имен делает вещи слишком сложными, ссылка на пространство имен не существует. Затем я нашел способ удалить пространство имен, чтобы упростить синтаксический анализ, который подходит для моего приложения. - person Aladdin Nassar; 01.12.2014
comment
Я, конечно, не стал бы защищать то, как это делает XPath 1.0, или что-либо еще, связанное с пространствами имен. Это просто то, с чем мы должны жить. - person Michael Kay; 01.12.2014

Вы можете сделать это с помощью 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);
}

Выход:

Author : Randal L. Schwartz
Author : brian d foy
Author : Tom Phoenix
Title : Learning Perl
person take    schedule 30.11.2014
comment
Он не просил решение LinqToXML, он просил решение XPath. - person Michael Kay; 01.12.2014
comment
@MichaelKay Все знают о точном характере вопроса. Предлагать альтернативные решения — это неплохо, поскольку это может привести к переоценке и переосмыслению проблемного пространства и решения. Высокомерие не является предпочтительной чертой характера Служащих Другим. - person Ottak; 01.12.2014
comment
Спасибо Оттак и МайклКей. Я ценю оба ваших ответа. Будут ли оба ваших решения работать, если узел ‹item› будет повторять печать названия и авторов для ‹item›? Я опубликовал третье решение, которое я придумал, чтобы ответить на мой первоначальный вопрос и масштабировать его до нескольких «элементов». - person Aladdin Nassar; 01.12.2014

Наконец-то я нашел ответ на свой вопрос. Я просто удалил пространство имен, которое слишком усложняло мой XPath. Приведенный ниже код С# работает. PrintKeyValue просто печатает 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());
            }
person Aladdin Nassar    schedule 01.12.2014