2009-08-21 3 views
0

Я пытаюсь разобрать немного данных из файла HTML, но моя инструкция Linq не работает. Вот XML/HTML. Ниже, как я могу извлечь строку «41.8; 12.23» из метатега geo.position? Спасибо!!Как извлечь метатег из XML/HTML с помощью Linq?

Вот мой Linq

String longLat = (String) 
     from el in xdoc.Descendants() 
       where 
       (string)el.Name.LocalName == "meta" 
       & el.FirstAttribute.Name == "geo.position" 
       select (String) el.LastAttribute.Value; 

Вот мой XDocument

<span> 
    <!--CTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dt --> 
    <html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
     <meta content="application/xhtml+xml; charset=utf-8" http-equiv="Content-Type" /> 
     <meta content="text/css" http-equiv="Content-Style-Type" /> 
     <meta name="geo.position" content="41.8;12.23" /> 
     <meta name="geo.placename" content="RomeFiumicino, Italy" /> 
     <title>RomeFiumicino, Italy</title> 
    </head> 
    <body /> 
    </html> 
</span> 

Edit: Мой запрос, как данные возвращает ничего. Кажется, что «внутренний» запрос возвращает список всех мета-элементов, а не только один элемент, который я хочу.

Edit: Следующий запрос Linq работает против того же XDocument для извлечь таблицу с именем класса = «данные»

var dataTable = 
     from el in xdoc.Descendants() 
     where (string)el.Attribute("class") == "data" 
     select el; 
+0

подчеркнут вашу HTML и нажмите на кнопку «Код» – Gregoire

+0

Смотрите эту страницу для полной ссылки разметки. http://stackoverflow.com/editing-help – Joel

+0

А как насчет добавления вашего linq-statement-that-is-not-working? –

ответ

4

span вокруг html тега?

Вы можете сделать это с помощью XLinq, но это будет поддерживать только хорошо сформированный XML. Вместо этого вы можете посмотреть на HTML Agility Pack.

Редактировать - Это работает для меня:

string xml = "..."; 
var geoPosition = XElement.Parse(xml).Descendants(). 
    Where(e => e.Name.LocalName == "meta" && 
     e.Attribute("name") != null && 
     e.Attribute("name").Value == "geo.position"). 
    Select(e => e.Attribute("content").Value). 
    SingleOrDefault(); 
+0

Спасибо большое, Торарин. Я использовал HTML Agility Pack, чтобы получить XDocumnent - пакет добавил Span. –

+1

Это не правильно сформированный XML? Конечно, это выглядит так, как синтаксический анализатор. –

+0

Да, это на самом деле. Я заметил недостающую двойную кавычку, но не заметил, что doctype был фактически преобразован в комментарий XML;) – Thorarin

1

Я согласен с Торариными - использовать пакет HTML Agility, это гораздо более надежными.

Однако я подозреваю, что проблема, с которой вы используете LinqToXML, связана с пространством имен. См. MSDN here, как обращаться с ними в ваших запросах.

"Если у вас есть XML, который находится в пространстве имен по умолчанию, вы все еще должны объявить переменную XNamespace, и объединить его с локальным именем, чтобы сделать квалифицированное имя, которое будет использоваться в запросе.

Один из наиболее распространенными проблемами при запросе деревьев XML является то, что если дерево XML имеет пространство имен по умолчанию, разработчик иногда пишет запрос, как если бы XML не был в пространстве имен ».

+0

Спасибо, Дэн. Да, я большой поклонник Agility Pack, который достал меня достаточно далеко, чтобы решить эту проблему. :) У меня есть другие запросы Linq, которые * делают * работают против одного и того же документа. Я добавил пример запроса, но не большую таблицу, которую он извлекает для меня. –

2

Готов поспорить, что проблема, с которой вы столкнулись, связана с неправильным ссылкой на пространство имен с помощью XmlNamespaceManager. Есть два способа сделать это:

string xml = 
     @"<span> 
    <!--CTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" 
     ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dt --> 
    <html xmlns=""http://www.w3.org/1999/xhtml""> 
    <head> 
    <meta content=""application/xhtml+xml; charset=utf-8"" http-equiv=""Content-Type"" /> 
     <meta content=""text/css"" http-equiv=""Content-Style-Type"" /> 
     <meta name=""geo.position"" content=""41.8;12.23"" /> 
     <meta name=""geo.placename"" content=""RomeFiumicino, Italy"" /> 
     <title>RomeFiumicino, Italy</title> 
    </head> 
    <body /> 
    </html> 
    </span>"; 

    string ns = "http://www.w3.org/1999/xhtml"; 
    XmlNamespaceManager nsm; 

    // pre-Linq: 
    XmlDocument d = new XmlDocument(); 
    d.LoadXml(xml); 
    nsm = new XmlNamespaceManager(d.NameTable); 
    nsm.AddNamespace("h", ns); 

    Console.WriteLine(d.SelectSingleNode(
     "/span/h:html/h:head/h:meta[@name='geo.position']/@content", nsm).Value); 

    // Linq - note that you have to create an XmlReader so that you can 
    // use its NameTable in creating the XmlNamespaceManager: 
    XmlReader xr = XmlReader.Create(new StringReader(xml)); 
    XDocument xd = XDocument.Load(xr); 
    nsm = new XmlNamespaceManager(xr.NameTable); 
    nsm.AddNamespace("h", ns); 

    Console.WriteLine(
     xd.XPathSelectElement("/span/h:html/h:head/h:meta[@name='geo.position']", nsm) 
      .Attribute("content").Value); 
+0

Спасибо, роберт. –

 Смежные вопросы

  • Нет связанных вопросов^_^