Как получить значение узла XML в виде строки при десериализации

Я отправляю XML в web-интерфейс ядра aspnet. Значение префикса пространства имен cfdi: определяется в содержащем узле:

<cfdi:Comprobante>
  <cfdi:Conceptos>
  </cfdi:Conceptos>
  <cfdi:Addenda>
    <bfa2:AddendaBuzonFiscal version="2.0" xmlns:bfa2="http://www.buzonfiscal.com/ns/addenda/bf/2"><bfa2:TipoDocumento nombreCorto="FAC" descripcion="Factura"/><bfa2:CFD totalConLetra="CINCUENTA Y DOS MIL QUINIENTOS OCHENTA Y NUEVE PESOS 64/100 M.N." observaciones="OBSERVACIONES"/><bfa2:Extra atributo="ClaveTransportista" valor="00328"/><bfa2:Extra atributo="NoRelacionPemex" valor="1-2"/>
    <bfa2:Extra atributo="NoConvenio" valor="5"/>
    </bfa2:AddendaBuzonFiscal>
    <Encabezado NumOrden="" NumFacturaOriginal="" FechaDePedido=""/>
    <Envio Calle="" NoExterior="" Colonia="" Localidad="" Municipio="" Estado="" Pais="" CodigoPostal="" NombreEnviar=""/><Detalle OrdenCompraLinea="10" GRNumber="GRN"/><Detalle OrdenCompraLinea="10" GRNumber="GRN"/><Detalle OrdenCompraLinea="10" GRNumber="GRN"/>
  </cfdi:Addenda>
</cfdi:Comprobante>

Для десериализации этого я сделал класс Comprobante:

public class Comprobante : IValidatableObject
{
    [Required]
    [XmlArray("Conceptos"), XmlArrayItem(typeof(Concepto), ElementName = "Concepto")]
    public List<Concepto> Conceptos { get; set; }

    public Addenda Addenda { get; set; }
}

Все сопоставлено со свойствами класса, кроме Addenda узел может получить что угодно - любое количество допустимых узлов XML - поэтому у меня нет определения класса. То есть Addenda узел может содержать n узлов, о которых я не знаю, информация проверяется на стороне получателя. Например, клиент может попросить добавить узел с номером заказа, другой может попросить имя покупателя. И т.п.

Если мне нужно получить все Addenda содержимое узла в виде строки, как я должен объявить его в классе?

1 ответ

Решение

Вы можете десериализовать произвольные данные XML в свободной форме, используя XmlSerializer помечая целевые свойства [XmlAnyElement],

Например, вы можете определить свой Addenda введите следующее:

[XmlRoot("Comprobante", Namespace = "http://cfdi")]
public class Comprobante : IValidatableObject
{
    [Required]
    [XmlArray("Conceptos"), XmlArrayItem(typeof(Concepto), ElementName = "Concepto")]
    public List<Concepto> Conceptos { get; set; }

    public Addenda Addenda { get; set; }
}

public class Addenda
{
    [XmlAnyElement]
    [XmlText]
    public XmlNode[] Nodes { get; set; }
}

Пример рабочей.Net скрипки № 1.

Или вы можете устранить Addenda введите полностью и замените его XmlElement свойство в содержащем типе:

[XmlRoot("Comprobante", Namespace = "http://cfdi")]
public class Comprobante : IValidatableObject
{
    [Required]
    [XmlArray("Conceptos"), XmlArrayItem(typeof(Concepto), ElementName = "Concepto")]
    public List<Concepto> Conceptos { get; set; }

    [XmlAnyElement("Addenda")]
    public XmlElement Addenda { get; set; }
}

Пример рабочей.Net скрипки № 2.

Заметки:

  • При применении без имени элемента, [XmlAnyElement] указывает, что член является массивом XmlElement или же XmlNode объекты, которые будут содержать все произвольные данные XML, которые не связаны с каким-либо другим членом в содержащем типе.

  • При применении с именем элемента (и необязательным пространством имен), [XmlAnyElement("Addenda")] указывает, что член является либо одним XmlElement объект или массив таких объектов, и будет содержать все произвольные элементы XML с именем <Addenda>, Использование этой формы устраняет необходимость в дополнительном Addenda тип.

  • Объединяя [XmlText] с [XmlAnyElement] позволяет десериализовать произвольный смешанный контент.

  • Если вы используете.NET Core, вам может понадобиться nuget System.Xml.XmlDocument.

Другие вопросы по тегам