Подскажите пожалуйста каким образом в XML документе найти узел и его дочерние элементы и при этом вернуть объект класса соответствующий этим данным. Вот пример: XML нужно вывести все дочерние элементы INSTANCE CLASSNAME="ORG"
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE CIM SYSTEM "CIM_DTD_V20.dtd"
[<!ENTITY lt "&#60;">
<!ENTITY gt ">">
<!ENTITY amp "&#38;">
<!ENTITY apos "'">
<!ENTITY quot """> ]>
<CIM CIMVERSION="2.0" DTDVERSION="2.2">
<DECLARATION>
<DECLGROUP>
<VALUE.OBJECT>
<INSTANCE CLASSNAME="Header">
<PROPERTY NAME="Date" TYPE="string">
<VALUE>01/11/2019</VALUE>
</PROPERTY>
<PROPERTY NAME="Application" TYPE="string">
<VALUE>*</VALUE>
</PROPERTY>
</INSTANCE>
</VALUE.OBJECT>
<VALUE.OBJECT>
<INSTANCE CLASSNAME="ORG">
<PROPERTY NAME="ID" TYPE="string">
<VALUE>1</VALUE>
</PROPERTY>
<PROPERTY NAME="ORG_NAME" TYPE="string">
<VALUE>Клиент у которого обслуживаем технику</VALUE>
</PROPERTY>
<PROPERTY NAME="ORG_SEARCHCODE" TYPE="string">
<VALUE>КЛИЕНТ-1</VALUE>
</PROPERTY>
<PROPERTY NAME="ORG_OID" TYPE="string">
<VALUE>282</VALUE>
</PROPERTY>
<PROPERTY NAME="RCT_NAME" TYPE="string">
<VALUE>Заказчик</VALUE>
</PROPERTY>
</INSTANCE>
</VALUE.OBJECT>
<VALUE.OBJECT>
<INSTANCE CLASSNAME="CI">
<PROPERTY NAME="ID" TYPE="string">
<VALUE>3</VALUE>
</PROPERTY>
<PROPERTY NAME="NAME" TYPE="string">
<VALUE>NULL</VALUE>
</PROPERTY>
<PROPERTY NAME="TOWN" TYPE="string">
<VALUE>NULL</VALUE>
</PROPERTY>
<PROPERTY NAME="ADR" TYPE="string">
<VALUE>NULL</VALUE>
</PROPERTY>
<PROPERTY NAME="MODEL" TYPE="string">
<VALUE>HP LaserJet</VALUE>
</PROPERTY>
<PROPERTY NAME="TID" TYPE="string">
<VALUE>NULL</VALUE>
</PROPERTY>
<PROPERTY NAME="SERNUM" TYPE="string">
<VALUE>NULL</VALUE>
</PROPERTY>
<PROPERTY NAME="SC" TYPE="string">
<VALUE>MFU-STANDART-1</VALUE>
</PROPERTY>
<PROPERTY NAME="CAT" TYPE="string">
<VALUE>МФУ</VALUE>
</PROPERTY>
<PROPERTY NAME="ORG_OID" TYPE="string">
<VALUE>282</VALUE>
</PROPERTY>
<PROPERTY NAME="BLOCKED" TYPE="string">
<VALUE>0</VALUE>
</PROPERTY>
</INSTANCE>
</VALUE.OBJECT>
Вот код запроса:
private static void ReadXML(string patch)
{
XDocument xdoc = XDocument.Load(patch);
var items = from xe in xdoc.Element("CIM").Element("DECLARATION").Element("DECLGROUP").Element("VALUE.OBJECT").Elements("INSTANCE")
where xe.Attribute("CLASSNAME").Value == "ORG"
select new Organization
{
Id = xe.Attribute("ID").Value,
Org_name = xe.Attribute("ORG_NAME").Value,
Org_searchcode = xe.Attribute("ORG_SEARCHCODE").Value,
Org_oid = xe.Attribute("ORG_OID").Value,
Rct_name = xe.Attribute("RCT_NAME").Value
};
foreach (var item in items)
Console.WriteLine("${item.Id} - {item.Org_name} - {item.Org_oid} -" +
"{item.Org_searchcode} - {item.Rct_name}");
}
Во-первых, элементов "VALUE.OBJECT" много, а не один. Поэтому нужно писать .Elements("VALUE.OBJECT")
- обратите внимание на множественное число (Elements).
Во-вторых, вы получили запросом коллекцию элементов "INSTANCE", а нужно продвинуться ещё на шаг глубже - к элементам "PROPERTY".
В-третьих, "ID", "ORG_NAME" и т. д. - это не названия атрибутов, а значения атрибута NAME
.
Итого:
var items =
from xe in xdoc
.Element("CIM").Element("DECLARATION").Element("DECLGROUP")
.Elements("VALUE.OBJECT").Elements("INSTANCE")
where xe.Attribute("CLASSNAME").Value == "ORG"
let ps = xe.Elements("PROPERTY")
select new Organization
{
Id = ps.First(p => p.Attribute("NAME").Value == "ID").Value,
Org_name = ps.First(p => p.Attribute("NAME").Value == "ORG_NAME").Value,
Org_searchcode = ps.First(p => p.Attribute("NAME").Value == "ORG_SEARCHCODE").Value,
Org_oid = ps.First(p => p.Attribute("NAME").Value == "ORG_OID").Value,
Rct_name = ps.First(p => p.Attribute("NAME").Value == "RCT_NAME").Value
};
Можно сократить код, используя метод Descendants
. Но его применение ухудшает производительность, поэтому на больших документах лучше оставить как есть.
Ещё можно написать метод расширения:
public static string GetValue(this IEnumerable<XElement> enumerable, string name)
{
return enumerable.First(p => p.Attribute("NAME").Value == name).Value;
}
С ним код становится намного короче:
var items =
from xe in xdoc.Descendants("INSTANCE")
where xe.Attribute("CLASSNAME").Value == "ORG"
let ps = xe.Elements("PROPERTY")
select new Organization
{
Id = ps.GetValue("ID"),
Org_name = ps.GetValue("ORG_NAME"),
Org_searchcode = ps.GetValue("ORG_SEARCHCODE"),
Org_oid = ps.GetValue("ORG_OID"),
Rct_name = ps.GetValue("RCT_NAME")
};
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Есть метод для связи между таблицами и биндинг к гриду
В бд есть поле типа longtext, в него записан массив такого типа
Значение 0 недопустимо для RowCountRowCount должен быть больше или равен 1