2014-11-03 2 views
2

фрагмент из XML-им запросов являетсяПолучить значение элемента XML с помощью XML для Linq

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<metadata created="2014-11-03T18:13:02.769Z" xmlns="http://example.com/ns/mmd-2.0#" xmlns:ext="http://example.com/ns/ext#-2.0"> 
    <customer-list count="112" offset="0"> 
     <customer id="5f6ab597-f57a-40da-be9e-adad48708203" type="Person" ext:score="100"> 
      <name>Bobby Smith</name> 
      <gender>male</gender> 
      <country>US</country> 
      <birth-span> 
       <start>1965-02-18</start> 
       <end>false</end> 
      </birth-span> 

Кодекса IM писать, чтобы получить элементов

GetCustomer = from c in XDoc.Descendants(ns + "customer") 
         select 
         new Customer 
         { 
          Name = c.Element(ns + "name").ToString(), 
          Gender = Convert.ToString(c.Element(ns + "gender")), 
          BeginDate = c.Elements("birth-span").Any() ? c.Element("start").Value.ToString() : "No data found" 

Проблема у меня есть, с birth-span, я никогда не получаю значение, если существует период рождения (есть некоторые записи, которые не содержат элемент рождаемости). Для записей, которые делают содержать при рождении пролета элемента я добавил переменную пространства имен, которое не работает (бросает ошибку, что объект не указывает на экземпляр)

BeginDate = c.Elements(ns + "birth-span").Any() ? c.Element(ns + "start").Value.ToString() : "No data found" 

Ив добавляют различные вариации, но либо я получить значение Нет данных или ошибка (Кажется, объект не установлен в экземпляр). Может ли кто-нибудь увидеть, что я делаю неправильно?

ответ

3

Вы лечения start как прямой потомок c (или customer), делая это:

BeginDate = c.Elements("birth-span").Any() ? 
    c.Element("start").Value.ToString() : 
    "No data found" 

Когда вы на самом деле хотите сделать относиться к start как прямой потомок birth-span элемента, как так:

BeginDate = c.Elements("birth-span").Any() ? 
    c.Element("birth-span").Element("start").Value.ToString() : 
    "No data found" 

Однако есть возможности для улучшения. Есть ли ноль или один элемент birth-span, или ноль или многие? Как кажется, это ноль или один, вы могли бы сделать это и сделать это немного понятнее:

var customers = from c in doc.Descendants("customer") 
       let birthSpan = c.Element("birth-span") 
       select new 
       { 
        Name = c.Element("name").Value, 
        Gender = c.Element("gender").Value, 
        BeginDate = birthSpan == null ? 
         "No data found" : 
         birthSpan.Element("start").Value 
       }; 

Кроме того, нет необходимости вызывать Convert.ToString или .ToString() на любом из них. Если вы хотите, string, .Value() будет делать. Если вы на самом деле хотите, набранный на что-то другое, непосредственно брось и пусть операторы преобразования делают работу:

var customers = from c in doc.Root.Descendants("customer") 
       let birthSpan = c.Element("birth-span") 
       select new 
       { 
        Name = (string)c.Element("name"), 
        Gender = (string)c.Element("gender"), 
        BeginDate = birthSpan == null ? 
         (DateTime?)null : 
         (DateTime?)birthSpan.Element("start") 
       }; 

Там есть большая статья о том, что here.

+0

'Пространство имен ', которое будет включено' ... (ns + "customer") ' –

+0

Спасибо - очень полезно. Прежде чем перейти к продвинутым теориям, я попытался получить базовый способ работы с использованием этого кода BeginDate = c.Elements («рождение»). Any()? c.Element («рождение») Элемент («начало»). Value.ToString(): «Данные не найдены», но все же это возвращает * «Нет данных»? * – Computer

+0

Вы повторно добавили 'ns + ', как предлагает @Thirisangu? Я удалил их, чтобы попытаться упростить, но они все равно будут необходимы в вашем коде. – Ocelot20

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