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

How to get an XML node value as string when deserializing

我正在向 aspnet 核心网站 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>

为了反序列化这个,我做了 class Comprobante:

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

    public Addenda Addenda { get; set; }
}

一切都映射到 class 属性,但是 Addenda 节点可以接收任何东西——任意数量的有效 XML 节点——所以我没有 class定义。 IE。 Addenda 节点可能包含 n 个我不知道的节点,信息在接收端验证。例如,客户可能会要求添加一个带有 PO 编号的节点,另一个客户可能会要求提供买家姓名。等等

如果我需要获取所有Addenda节点内容为字符串,我应该如何在class中声明它?

您可以使用 XmlSerializer 通过使用 [XmlAnyElement].

标记目标属性来反序列化任意、自由格式的 XML 数据

例如您可以按如下方式定义 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]指定成员是XmlElement或[=19=的数组] 对象将包含所有任意 XML 数据,这些数据未绑定到包含类型中的某些其他成员。

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

  • 结合[XmlText][XmlAnyElement]允许反序列化任意混合内容。

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