Я новичок в XML и хочу создать XML-документ из таблицы данных.
У меня есть DataTable со следующими данными:
Number DeptNo DeptName State Date Year DeptCode ELP
123A 1001 DESC JR PA 12/12/2021 2021 74-123 Y
123A 1002 PHIL JR NY 09/12/2021 2021 74-124 Y
123A 1003 GILB JR CA 08/12/2021 2021 74-125 N
123A 1004 THEO JR AZ 07/12/2021 2021 74-126 N
123A 1005 HARR JR NV 06/12/2021 2021 74-127 Y
123A 1001 DESC JR FED 06/12/2021 2021 74-123 N
123A 1002 PHIL JR FED 09/12/2021 2021 74-124 N
Мне нужно создать файл XML из данных выше DataTable, как показано ниже:
<Root>
<Type>MyType</Type>
<FileDate>12/15/2022</FileDate>
<Version>2.0</Version>
<Department>
<Number>123A</Number>
<Id>0000</Id>
<Trust>
<DeptNo>1001</DeptNo>
<DeptName>DESC JR</DeptName>
<DeptCode>74-123</DeptCode>
<DepartmentData>
<State>PA</State>
<Date>12/12/2021</Date>
<Year>2021</Year>
<ELP>Y</ELP>
</DepartmentData>
<DepartmentData>
<State>FED</State>
<Date>12/12/2021</Date>
<Year>2021</Year>
<ELP>N</ELP>
</DepartmentData>
</Trust>
<Trust>
<DeptNo>1002</DeptNo>
<DeptName>PHIL JR</DeptName>
<DeptCode>74-124</DeptCode>
<DepartmentData>
<State>NY</State>
<Date>09/12/2021</Date>
<Year>2021</Year>
<ELP>Y</ELP>
</DepartmentData>
<DepartmentData>
<State>FED</State>
<Date>09/12/2021</Date>
<Year>2021</Year>
<ELP>N</ELP>
</DepartmentData>
</Trust>
<Trust>
<DeptNo>1003</DeptNo>
<DeptName>GILB JR</DeptName>
<DeptCode>74-125</DeptCode>
<DepartmentData>
<State>CA</State>
<Date>08/12/2021</Date>
<Year>2021</Year>
<ELP>N</ELP>
</DepartmentData>
</Trust>
<!-- Other Trust nodes skipped -->
</Department>
</Root>
Я пробовал следующее, но это не дает мне ожидаемого результата:
Как я могу перебирать строки с данными для создания XML-документа?





Ваша основная проблема в том, что вы создаете только один элемент <Trust>. Требуемый XML имеет несколько повторяющихся элементов <Trust>, поэтому вам нужно переместить создание этих элементов внутрь лямбды dt.AsEnumerable().
У вас также есть ошибка с элементом <Id>: вы создаете элемент с именем <ID>, а не <Id>. XML чувствителен к регистру, поэтому элементы всегда должны создаваться с правильным регистром.
Наконец, предложение: вы жестко кодируете отдел Number как "123A", однако вы можете легко сгруппировать строки DataTable по значению столбца Number, а затем написать групповой ключ вместо жестко закодированного значения.
Собрав все вместе, ваш код должен выглядеть так:
// Group the rows by Department (all 123A in your question).
var departments = dt.AsEnumerable().GroupBy(r => r.Field<string>("Number"));
// Generate the root element
var root = new XElement("Root",
new XElement("Type", "MyType"),
new XElement("FileDate", "12/15/2022"),
new XElement("Version", "2.0"),
departments.Select(
d =>
new XElement("Department",
new XElement("Number", d.Key),
new XElement("Id", "0000"), // Fixed, was ID
d.Select(
r =>
new XElement("Trust",
new XElement("DeptNo", r.Field<string>("DeptNo")),
new XElement("DeptName", r.Field<string>("DeptName")),
new XElement("DeptCode", r.Field<string>("DeptCode")),
new XElement("DepartmentData",
new XElement("State", r.Field<string>("State")),
new XElement("Date", r.Field<string>("Date")),
new XElement("Year", r.Field<string>("Year")),
new XElement("ELP", r.Field<string>("ELP"))
)
)
)
)
)
);
Не должно быть необходимости создавать узел XDeclaration, он должен быть написан автоматически, когда вы сериализуете свой XElement в свой окончательный выходной поток.
Демонстрационная рабочий пример здесь.
Но как сгруппировать по «DeptNo»? Я обновил DataTable и ожидаемый XML. Извините, я не упомянул об этом раньше в вопросе.
Вы можете добавить дополнительный GroupBy(), чтобы дополнительно сгруппировать строки отдела по номеру отдела, например:
// Group the rows by Department (all 123A in your question).
var departments = dt.AsEnumerable().GroupBy(r => r.Field<string>("Number"));
// Generate the root element
var root = new XElement("Root",
new XElement("Type", "MyType"),
new XElement("FileDate", "12/15/2022"),
new XElement("Version", "2.0"),
departments.Select(
d =>
new XElement("Department",
new XElement("Number", d.Key),
new XElement("Id", "0000"), // Fixed, was ID
// Group Departments by DeptNo. Also collect DeptName and DeptCode in the Key to use later (we assume they are consistent for each DeptNo).
d.GroupBy(r => (DeptNo : r.Field<string>("DeptNo"), DeptName : r.Field<string>("DeptName"), DeptCode : r.Field<string>("DeptCode"))).Select(
deptNo =>
new XElement("Trust",
new XElement("DeptNo", deptNo.Key.DeptNo),
new XElement("DeptName", deptNo.Key.DeptName),
new XElement("DeptCode", deptNo.Key.DeptCode),
deptNo.Select(data =>
new XElement("DepartmentData",
new XElement("State", data.Field<string>("State")),
new XElement("Date", data.Field<string>("Date")),
new XElement("Year", data.Field<string>("Year")),
new XElement("ELP", data.Field<string>("ELP"))
)
)
)
)
)
)
);
Демонстрационная рабочий пример №2 здесь.
Это работает. DataTable будет содержать только строки с номером «123A». Но как сгруппировать по «DeptNo»? Я обновил DataTable и ожидаемый XML. Извините, я не упомянул об этом раньше в вопросе.
Я пытался добавить эту дополнительную группу, но получал повторяющиеся результаты. Вы спасли мой день!!
Следующее может быть полезно: stackoverflow.com/questions/73638292/…