Я пытаюсь получить имя тега XML в свойстве класса при выполнении десериализации XML.Мне нужно имя как свойство, так как несколько тегов XML совместно используют один и тот же класс.XML и связанные с ним классы определены ниже.
У меня есть ответ XML, который я получаю в формате:
<Data totalExecutionTime="00:00:00.0467241">
<ItemNumber id="1234" order="0" createdDate="2017-03-24T12:07:09.07" modifiedDate="2018-08-29T16:59:19.127">
<Value modifiedDate="2017-03-24T12:07:12.77">ABC1234</Value>
<Category id="5432" parentID="9876" itemOrder="0" modifiedDate="2017-03-24T12:16:23.687">The best category</Category>
... <!-- like 100 other elements -->
</ItemNumber>
</Data>
Десериализация выполняется следующим образом:
XmlSerializer serializer = new XmlSerializer(typeof(ItemData));
using (TextReader reader = new StringReader(response))
{
ItemData itemData = (ItemData)serializer.Deserialize(reader);
}
И класс для верхнего уровня, ItemData
:
[Serializable]
[XmlRoot("Data")]
public class ItemData
{
[XmlAttribute("totalExecutionTime")]
public string ExecutionTime { get; set; }
[XmlElement("ItemNumber", Type = typeof(ItemBase))]
public List<ItemBase> Items { get; set; }
}
ItemBase
определяется как:
[Serializable]
public class ItemBase
{
[XmlElement("Value")]
public virtual ItemProperty ItemNumber { get; set; } = ItemProperty.Empty;
[XmlElement("ItemName")]
public virtual ItemProperty Category { get; set; } = ItemProperty.Empty;
... // like 100 other properties
}
И, наконец, ItemProperty
:
public class ItemProperty : IXmlSerializable
{
public static ItemProperty Empty { get; } = new ItemProperty();
public ItemProperty()
{
this.Name = string.Empty;
this.Value = string.Empty;
this.Id = 0;
this.Order = 0;
}
public string Name { get; set; }
[XmlText] // no effect while using IXmlSerializable
public string Value { get; set; }
[XmlAttribute("id")] // no effect while using IXmlSerializable
public int Id { get; set; }
[XmlAttribute("itemOrder")] // no effect while using IXmlSerializable
public int Order { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
string name = reader.Name;
this.Name = name;
string val = reader.ReadElementString();
this.Value = val;
if (reader.HasAttributes)
{
string id = reader.GetAttribute("id");
this.Id = Convert.ToInt32(id);
string itemOrder = reader.GetAttribute("itemOrder");
this.Order = Convert.ToInt32(itemOrder);
string sequence = reader.GetAttribute("seq");
this.Sequence = Convert.ToInt32(sequence);
}
// it seems the reader doesn't advance to the next element after reading
if (reader.NodeType == XmlNodeType.EndElement && !reader.IsEmptyElement)
{
reader.Read();
}
}
public void WriteXml(XmlWriter writer)
{
throw new NotImplementedException();
}
}
Смысл реализации интерфейса IXmlSerializable
заключается в том, что в конечном итоге мне нужно имя тега XML, который хранится как ItemProperty
, и эта информация не захватывается при использовании атрибутов класса / свойства XML.Я полагаю, что это так, поскольку атрибуты определяют, какой класс использовать для десериализации, и обычно каждый тег XML имеет связанный класс.Я не хочу идти в этом направлении, так как в ответе может быть так много разных тегов, и все они имеют одинаковые атрибуты.Следовательно, класс ItemProperty
.
Я также пытался передать имя тега через параметризованный конструктор в ItemProperty
и установить там свойство name, но когда выполняется десериализация, он использует значение по умолчанию.конструктор, а затем устанавливает значения свойств, так что это не вариант.
Отражение также не работает, поскольку класс всегда ItemProperty
и поэтому не имеет уникального имени.
Может быть, то, как я структурирую атрибуты XML, можно сделать по-другому, чтобы достичь того, что я пытаюсь сделать, но я не вижу этого.
Я открыт для любого способа решения этой проблемы,но я уверен, что это влечет за собой реализацию IXmlSerializable.ReadXml()
.Я знаю, что задача XmlReader
состоит в том, чтобы прочитать весь XML и продвинуть читателя до конца текста, но мне немного неясно, как это сделать.
TLDR: Как правильно реализовать IXmlSerializable.ReadXml()
при записи имени тега XML, значения тега и всех атрибутов в свойства класса?
Редактировать: с помощьюобновленный метод ReadXml
, я получаю все данные, необходимые на уровне ItemProperty
, но в классе ItemData
список Items
содержит только один элемент.Я предполагаю, потому что я не продвигаю читателя должным образом.