如何在反序列化时将XML节点值作为字符串获取

时间:2017-12-08 17:47:58

标签: c# xml xmlserializer

我正在向aspnet核心web api发送XML。名称空间前缀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 个答案:

答案 0 :(得分:1)

您可以使用XmlSerializer通过使用[XmlAnyElement]标记目标属性来反序列化任意的自由格式XML数据。

E.g。您可以按如下方式定义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; }
}

示例working .Net fiddle #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; }
}

示例working .Net fiddle #2

注意:

  • 当应用而不使用元素名称时,[XmlAnyElement]指定该成员是XmlElementXmlNode个对象的数组,其中包含所有任意对象未绑定到包含类型中某个其他成员的XML数据。

  • 使用元素名称(和可选命名空间)时,[XmlAnyElement("Addenda")]指定该成员是单个XmlElement对象或其数组对象,并将包含名为<Addenda>的所有任意XML元素。使用此表单无需额外的Addenda类型。

  • [XmlText][XmlAnyElement]结合使用可以对任意混合内容进行反序列化。

  • 如果您使用的是.NET Core,则可能需要注意System.Xml.XmlDocument