#c# #asp.net #xml #linq-to-xml
#c# #asp.net #xml #linq-to-xml
Вопрос:
У меня есть следующий XML-файл. Я пытаюсь прочитать узел StartDate элемента dept, но не хочу читать узел «StartDate» любого из остальных дочерних элементов, таких как «DeptRoles».
<dept operationalStatus="active" primaryRole="Admin" depChangeDate="20130420">
<startDate type="legal">20130401</startDate>
<endDate type="legal"></endDate>
<startDate type="operational">20130320</startDate>
<endDate type="operational"></endDate>
<DeptRoles>
<DeptRole name="Other dept" status="active">
<startDate type="legal">20130401</startDate>
<endDate type="legal"></endDate>
<startDate type="operational">20130320</startDate>
<endDate type="operational"/>
<isPrimary/>
</DeptRole>
</DeptRoles>
</dept>
Это мой код на c #. Этот код также получает элемент DeptRole StartDate, который мне не нужен.
public static List<organisation> Getorgdata(string data)
{
List<organisation> listorgdata = new List<organisation>();
XmlReader xmlReader = XmlReader.Create(new StringReader(data));
while (xmlReader.Read())
{
if (xmlReader.NodeType == XmlNodeType.Element)
{
organisation record = new organisation();
if (xmlReader.HasAttributes amp;amp; xmlReader.Name == "dept")
{
record.orgOperationalStatus = xmlReader.GetAttribute("operationalStatus");
record.orgLegalStatus = xmlReader.GetAttribute("legalStatus");
}
else if (xmlReader.Name == "name")
{
record.orgName = xmlReader.ReadElementString("name");
}
else if (xmlReader.Name == "startDate" || xmlReader.Name == "endDate")
{
if (xmlReader.GetAttribute("type") == "legal")
{
record.orgLegalStartDate = xmlReader.ReadElementString("startDate");
record.orgLegalEndDate = xmlReader.ReadElementString("endDate");
}
else if (xmlReader.GetAttribute("type") == "operational")
{
record.orgOperationalStartDate = xmlReader.ReadElementString("startDate");
record.orgOperationalEndDate = xmlReader.ReadElementString("endDate");
listorgdata.Add(record);
}
}
}
}
return listorgdata;
}
Ответ №1:
Я бы использовал LINQ для XML (как предлагали другие). Ниже приведен пример кода, который в некоторой степени соответствует вашему опубликованному коду — объяснение кода следует ниже.
public static List<organisation> Getorgdata(string data)
{
List<organisation> listorgdata = new List<organisation>();
XDocument xDoc = XDocument.Parse(data);
listorgdata = xDoc.Root.Elements("dept")
.Select(x => new organisation()
{
orgOperationalStatus = (string)x.Attribute("operationalStatus"),
orgLegalStartDate = (string)x.Elements("startDate")
.Where(x1 => (string)x1.Attribute("type") == "legal")
.First(),
orgOperationalStartDate = (string)x.Elements("startDate")
.Where(x1 => (string)x1.Attribute("type") == "operational")
.First()
}).ToList();
return listorgdata;
}
Первое, что делает приведенный выше код, это загружает XML в XDocument с XDocument.Parse
помощью метода.
Затем запрос анализирует XML-документ и возвращает список заполненных organization
объектов. Это выглядит примерно так.
- Получить все
<dept>
элементы (и дочерние элементы). - Для каждого
<dept>
элемента создайте новый экземплярorganisation
и присвоите значение атрибута «OperationalStatus»operationalStatus
свойству oforganisation
.(string)
Приведение будет корректно обрабатывать ситуацию, когда указанный атрибут отсутствует. - Для получения допустимой даты начала мы выполняем запрос к
<startDate>
дочерним элементам<dept>
элемента, беря первый, у которого атрибут «type» равен «legal». - Для даты начала работы мы выполняем запрос, аналогичный номеру 3, за исключением того, что он ищет «рабочий».
- Преобразуйте
IEnumerabale<T>
результат в список, вызвав метод.ToList()
расширения.
Это может быть не самым эффективным, и оно не охватывает все свойства, которые у вас есть в исходном коде, но это должно, по крайней мере, помочь вам двигаться в правильном направлении. Например, если вы хотите получить атрибут «primaryRole», вы бы просто добавили следующую строку в new organisation()
блок:
orgPrimaryRole = (string)x.Attribute("primaryRole"),
Если вам нужны данные, <DeptRoles>
вы можете получить их, но это немного сложнее.
Если вы предпочитаете синтаксис запроса синтаксису метода, это будет выглядеть так:
listorgdata = (from x in xDoc.Root.Elements("dept")
select new
{
orgOperationalStatus = (string)x.Attribute("operationalStatus"),
orgLegalStartDate = (from x1 in x.Elements("startDate")
where (string)x1.Attribute("type") == "legal"
select (string)x1).First(),
orgOperationalStartDate = (from x1 in x.Elements("startDate")
where (string)x1.Attribute("type") == "operational"
select (string)x1).First()
}).ToList();
Ответ №2:
Если я добавлю КАТАЛОГ
<CATALOG>
<dept operationalStatus="active" primaryRole="Admin" depChangeDate="20130420">
<startDate type="legal">20130401</startDate>
<endDate type="legal"></endDate>
<startDate type="operational">20130320</startDate>
<endDate type="operational"></endDate>
<DeptRoles>
<DeptRole name="Other dept" status="active">
<startDate type="legal">20130401</startDate>
<endDate type="legal"></endDate>
<startDate type="operational">20130320</startDate>
<endDate type="operational"/>
<isPrimary/>
</DeptRole>
</DeptRoles>
</dept>
</CATALOG>
используя System.Xml.Linq; Вы можете получить свой список :
XElement myXML = XElement.Load(@"C:UsersUserDesktopmyXML.xml");
var deptDescendantsList = (from ep in myXML.Descendants("dept")
select ep.Elements("startDate")).ToList();
Комментарии:
1. как я узнаю, имеет ли эта дата начала тип legal или operational. не могли бы вы, пожалуйста, изменить этот запрос, если я добавлю deptid=anynumber в узел отдела. как можно использовать этот запрос Lin2Xml, чтобы получить только элемент StartDate, например, deptid =anynumber
Ответ №3:
Я не уверен, как создать запрос, который точно соответствует вашим потребностям. Попробуйте добавить этот запрос к вашим потребностям. http://msdn.microsoft.com/en-us/library/bb387061.aspx содержит некоторую информацию о запросах linq2xml
XmlReader xmlReader = XmlReader.Create(new StringReader(data));
XDocument d = XDocument.Load(xmlReader);
var startDates = from item in d.Root.Descendants()
where item.Name == "startDate" amp;amp; item.Parent.Name == "dept" amp;amp; item.Parent.Attribute("deptid").Value == "anynumber"
select item;
// iterate over the startDates and do your magic
Ответ №4:
Попробуйте это :
var readSpecific = из a в xd.Потомки («отделы»)
select new
{
LegalStartDate = a.Element("dept").Elements("startDate").First(cc => cc.Attribute("type").Value == "legal").Value,
LegalEndDate = a.Element("dept").Elements("endDate").First(cc => cc.Attribute("type").Value == "legal").Value,
OperationalStartDate = a.Element("dept").Elements("startDate").First(cc => cc.Attribute("type").Value == "operational").Value,
OperationEndDate = a.Elements("dept").Elements("endDate").First(cc => cc.Attribute("type").Value == "operational").Value
};