#c# #xml
Вопрос:
Это базовый макет файла.
<InvoiceNo>1065178</InvoiceNo>
<InstallationId>10903</InstallationId>
<CreateDate>2019-03-29T00:00:00</CreateDate>
<AccountNo>123456</AccountNo>
<BalanceDue>1024.40</BalanceDue>
<StatementDate>2019-04-01T00:00:00</StatementDate>
<NoPrint>0</NoPrint>
<Pages>
<Page templatepage="1">
<OtherFields>
<Key name="Instructions1"><Value>Please write your account number on your check!</Value></Key>
<Key name="AgeTitle1"><Value>CURRENT </Value></Key>
<Key name="AgeTitle2"><Value>30 DAYS </Value></Key>
<Key name="AgeTitle3"><Value>60 DAYS </Value></Key>
<Key name="AgeTitle4"><Value>90 DAYS </Value></Key>
</OtherFields>
</Page>
</Pages>
</Invoice>
Я могу получить верхний уровень, Счет Нет, Создать дату, но не смог добраться до пар имя/значение ключа, где находится большая часть данных. Вот моя последняя попытка загрузить его в словарь, он загружает весь узел в одну запись, и мне нужно разделить его. Я не вкладываюсь в использование словаря, это просто моя последняя попытка. Любая помощь будет очень признательна.
string xmlfile = @"C:/data//WDM/CUSTInvoiceData2019032902.xml";
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(xmlfile);
XmlNodeList nodelist = xmldoc.SelectNodes("//*[local-name()='OtherFields']");
Dictionary<string, string> dictXml = new Dictionary<string, string>();
foreach (XmlNode node in nodelist)
{
foreach (XmlNode elementpair in node.ChildNodes)
{
dictXml.Add(elementpair.Attributes["Key name"].Value,
elementpair.Attributes["value"].Value);
}
}
Комментарии:
1. В стороне: что делать, если счет-фактура содержит несколько страниц?
2. Позвольте мне угадать: в XML много узлов счетов-фактур? И покажите, как должен выглядеть окончательный CSV-файл.
3. Существует нижний колонтитул, который помечает следующую страницу как продолжение, и это будет новая строка в csv-файле.
Ответ №1:
Используйте Сериализацию Xml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication2
{
class Program
{
const string FILE = @"c:TEMPTEST.XML";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILE);
XmlSerializer serializer = new XmlSerializer(typeof(Invoice));
Invoice invoice = (Invoice)serializer.Deserialize(reader);
}
}
public class Invoice
{
public string InvoiceNo { get; set; }
public string InstallationId { get; set; }
public DateTime CreateDate { get; set; }
public string AccountNo { get; set; }
public decimal BalanceDue { get; set; }
public DateTime StatementDate { get; set; }
public int NoPrint { get; set; }
[XmlArray("Pages")]
[XmlArrayItem("Page")]
public Page[] pages { get; set; }
}
public class Page
{
[XmlAttribute]
public int templatepage { get; set; }
[XmlArray("OtherFields")]
[XmlArrayItem("Key")]
public Key[] keys { get; set; }
}
public class Key
{
[XmlAttribute]
public string name { get; set; }
public Value Value { get; set; }
}
public class Value
{
[XmlText]
public string value { get; set; }
}
}
Комментарии:
1. Попробуйте это, и я смогу перейти к счету — фактуре товаров верхнего уровня. Например, InvoiceNo, но я не смог получить доступ к массиву других полей?
2. Я добавил изображение выше. Все, что сделал Id, — это добавил в начале XML отсутствующий корневой тег<Счет-фактура>
Ответ №2:
Почти готово
- Вы ошибаетесь в имени атрибута не
.Attributes["Key name"]
но.Attributes["name"]
- Вы должны получить значение, а не атрибут, также вы должны получить значение дочерней заметки
foreach (XmlNode elementpair in node.ChildNodes)
{
var key = elementpair.Attributes["name"].Value;
var val = elementpair.ChildNodes[0].ChildNodes[0].Value;
dictXml.Add(key,val);
}
Комментарии:
1. Спасибо за это, и это выглядело хорошо, пока я не столкнулся с пустым значением и не обнаружил, что я не могу иметь значение NULL в словаре без создания пользовательского словаря.
Ответ №3:
Вы выбираете Key
элементы и ищете два атрибута: Key name
и value
. Но элементы не имеют атрибутов с этими именами. Ключ находится в вызываемом атрибуте name
, а соответствующее значение находится в вызываемом дочернем элементе (не атрибуте) Value
.
Ответ №4:
В вашем макете файла вы забыли добавить <Invoice>
в начале.
И это более простой способ выполнения запроса. "//Key"
XmlNodeList nodelist = xmldoc.SelectNodes("//Key");
Dictionary<string, string> dictXml = new Dictionary<string, string>();
foreach (XmlNode node in nodelist)
dictXml[node.Attributes[0].Value] = node.InnerText;