#c# #.net-3.5 #elements #linq-to-xml
#c# #.net-3.5 #элемент #linq-to-xml
Вопрос:
Я в тупике (снова) из-за неправильного понимания XDocument / Linq. Для приведенного ниже XML у меня есть nameEn
provinceCode
переменные and as в моем коде. Я пытаюсь идентифицировать code
(например, s0000002
) и nameFr
учитывая, что у меня есть два других элемента. Объединенные provinceCode
и NameEn
уникальны в XML (без дублирования).
<siteList>
<site code="s0000001">
<nameEn>Edmonton</nameEn>
<nameFr>Edmonton</nameFr>
<provinceCode>AB</provinceCode>
</site>
<site code="s0000002">
<nameEn>Algonquin Park</nameEn>
<nameFr>Parc Algonquin</nameFr>
<provinceCode>ON</provinceCode>
</site>
...
</siteList>
Вот код, который я пытаюсь (мой XML находится в «загруженном» XDocument:
selectedProvince = "ON";
selectedCity = "Algonquin Park";
strSiteCode = loaded.Descendants("site")
.Where(x => x.Element("provinceCode").Value == selectedProvince)
.Where(x => x.Element("nameEn").Value == selectedCity)
.Select(x => x.Element("code").Value)
.ToString();
strNameFR = loaded.Descendants("site")
.Where(x => x.Element("provinceCode").Value == selectedProvince)
.Where (x => x.Element("nameEn").Value == selectedCity)
.Select(x => x.Element("nameFr").Value)
.ToString();
Строка strSiteCode
возвращает: System.Linq.Enumerable WhereSelectEnumerableIterator
2[System.Xml.Linq.XElement,System.String] and
strNameFR returns
«»`.
Я не могу понять, как должен выглядеть рабочий код. Спасибо за любую помощь.
Doug
Ответ №1:
Попробуйте
var result = loaded.Descendants("site")
.Where(x => (x.Element("provinceCode").Value == selectedProvince) amp;amp;
(x.Element("nameEn").Value == selectedCity) )
.Select(x => x.Element("code").Value)
.SingleOrDefault();
if (result != null)
{
strSiteCode = result.ToString();
}
Select()
Вызов возвращает коллекцию (которая, в вашем случае, имеет только один элемент). Поэтому вам придется вызвать SingleOrDefault()
(или Single()
), чтобы получить один элемент. Кроме того, я удалил второе Where()
и включил условие в первое Where()
.
Комментарии:
1. Привет, Бала. Я не мог заставить это работать. Я продолжал получать эту ошибку «Оператор ‘amp;amp;’ не может быть применен к операндам типа ‘bool’ и ‘System.Xml.Linq. XElement'» Спасибо
2. @Doug Ах! Я кое-что упустил при объединении двух
Where()
элементов. Теперь это исправлено.
Ответ №2:
Имейте в виду, что возможно, что метод «x.Element (…)» вернет значение null, в результате чего доступ к «Значению» для него приведет к нулевой ссылке. Это предполагает, что ваш xml не всегда может иметь provinceCode или nameEn . Если это произойдет, у вас не возникнет проблем, но вы все равно не захотите помещать эту возможную нулевую ссылку в код выпуска. Следующее решает проблему null ref.
var site = loaded
.Descendants("site")
.FirstOrDefault(x => (string)x.Element("provinceCode") == selectedProvince amp;amp;
x => (string)x.Element("nameEn") == selectedCity);
if (site == null)
{
return
}
var siteCode = (string)site.Attribute("code");
var nameFr = (string)site.Element("nameFr");
Ответ №3:
Я бы, вероятно, переписал его так:
- получите список совпадающих
<site>
узлов один раз - перебор всех совпадений (обычно только одного)
- получить
code
атрибут иnameFr
элемент из этих совпадающих элементов
Код будет выглядеть следующим образом:
// determine the matching list of <site> nodes ...
var selectedSites = loaded
.Descendants("site")
.Where(x => x.Element("provinceCode").Value == selectedProvince)
.Where(x => x.Element("nameEn").Value == selectedCity);
// iterate over all matching <site> nodes
foreach (var site in selectedSites)
{
// grab the code attribute and nameFr element from <site> node
var siteCode = site.Attribute("code").Value;
var nameFR = site.Element("nameFr").Value;
}
Комментарии:
1. Большое спасибо. В итоге я получил почти тот же код, с которого начал. В вашем коде было то, чего не было в моем, так это то, что вы использовали «Атрибут» вместо «Элемент». Вот почему код для strSiteCode не работал. (спасибо !!) И мой код для strNameFR действительно работал, за исключением того, что я случайно сделал это =»» во время тестирования. (Ого! Бьет по лбу)
2. @Doug: классический ПИКНИК : проблема в кресле, а не в компьютере 🙂
3. Кстати, при использовании этого кода может возникнуть несколько проблем с нулевой ссылкой. 🙂
4. @xixonia: да, очевидно — это абсолютно предполагало, что «provinceCode» и «nameEn» на узлах <site> всегда есть (а также атрибут «code» на <site> и элемент «nameFr» внутри этого узла) — наверняка! Я не пытался показать, как идеально обрабатывать все потенциальные ошибки …
5. Правильно. Я просто был взволнован, потому что явные операторы в наборе классов XNode действительно хороши для подобных вещей. Использование ‘(string)x.Element (…)’ такое же, как ‘x.Element (…).Value’, за исключением того, что если элемент имеет значение null, он просто вернет null при приведении. 🙂