2013-03-12 3 views
1

Я использую Linq для Xml для анализа некоторых сообщений xml, исходящих из старой системы. Одно из сообщений поступает как пары Name/Value. Поэтому я выполняю поиск по имени, а затем пытаюсь получить эквивалентное значение. Однако, когда значение пусто (<Value/>), мой код выбрасывает ошибку Input string was not in a correct format.Linq to Xml - Input String

Я пытаюсь найти лучший способ решить эту проблему. Любые предложения были бы с благодарностью (Пытаемся заполнить свойство с помощью NULL int int int).

Код Пример:

myRecord.myField= xdoc.Descendants("Information") 
         .Where(x => (string)x.Element("Name") == "myField") 
         .Select(x => (int?)x.Element("Value")).FirstOrDefault(); 

XML-фрагмент:

<Information> 
     <Name>myField</Name> 
     <Value /> 
    </Information> 

Всегда оценить обратную связь/вход.

Благодаря,

S

ответ

3

Когда элемент пуст, то это значение равно String.Empty, который не может быть обработан в виде целого числа. Таким образом, вы должны относиться к этому делу вручную:

myRecord.myField = xdoc.Descendants("Information") 
         .Where(x => (string)x.Element("Name") == "myField") 
         .Select(x => x.Element("Value")) 
         .Select(v => (v == null || v.IsEmpty) ? null : (int?)v) 
         .FirstOrDefault(); 
+1

Выбросите NullReferenceException, когда нет такого элемента (что, вероятно, не место здесь, но стоит знать) – MarcinJuraszek

+0

@MarcinJuraszek Неа, он не будет Это условие будет обрабатывать без вести элемент '(v == null || v.IsEmpty) ' –

+0

Хм, вам пришлось обновить ваш ответ, пока я печатал :) – MarcinJuraszek

0

Существует уже правильный ответ при условии, но я думаю, что немного больше объяснение было бы полезно.

Все дело о XElement to Nullable<T> explicit conversion. Берегись этот пример, чтобы увидеть, что происходит:

XElement element = null; 
// returns null 
int? value = (int?)element; 

element = new XElement("test", 1); 
// returns 1 
value = (int?)element; 

element = new XElement("test"); 
// throws FormatException 
value = (int?)element; 

(int?)xElementInstance возвращается null только, где элемент является null. В противном случае обрабатывается int parsing, который генерирует исключение, когда XElement.Value не является целым числом (например, в случае, когда Value не существует, так что это как int.Parse(String.Empty)).

Вы должны проверить is XElement set и does XElement has value перед преобразованием:

if (element == null) 
    return null; 
else if (element.IsEmpty) 
    return null 
else if (string.IsNullOrEmpty(element.Value)) 
    return null 
else 
    return (int?)element; 

Что можно легко сделать с помощью встроенного заявление:

(element == null || element.IsEmpty || string.IsNullOrEmpty(element.Value) ? null : (int?)element) 

Чтобы подвести итог, следующий код делать то, что вы хотите - принимает int? от XElement, событие, когда элемент не имеет значения:

element = new XElement("test"); 
// returns null 
value = element == null || element.IsEmpty || string.IsNullOrEmpty(element.Value) ? null : (int?)element; 
+0

Если вы используете 'XElement.Parse ("") ', то' IsEmpty' вернет 'false', но' Value' вернет пустую строку, и преобразование вызовет 'FormatException'. –

+0

Вы правы! Я этого не знал, поэтому большое спасибо! Обновлен мой ответ. – MarcinJuraszek

0

Это должно работать:

public static class Extensions 
{ 
    public static int? ToInt32(this XElement element) 
    { 
     if (element == null) return null; 
     if (element.IsEmpty) return null; 

     // If the element is declared as <Value></Value>, 
     // IsEmpty will be false, but the value will be an empty string: 
     if (string.IsNullOrEmpty(element.Value)) return null; 

     return XmlConvert.ToInt32(element.Value); 
    } 
} 

myRecord.myField = doc.Descendants("Information") 
    .Where(x => (string)x.Element("Name") == "myField") 
    .Select(x => x.Element("Value").ToInt32()).FirstOrDefault();