如何在根元素的反序列化 class 中设置 xmlns 前缀

How set xmlns prefix in deserialization class for the root element

我使用 xmltocsharp site 创建了 class 帮助程序来反序列化特定的 XML,但是没有用,问题出在根元素上。这是根元素(RESP_HDR 和 RESP_BODY 已折叠):

<?xml version="1.0" encoding="UTF-8"?>
<SII:RESPUESTA xmlns:SII="http://www.sii.cl/XMLSchema">
    + <SII:RESP_HDR>
    + <SII:RESP_BODY>
</SII:RESPUESTA>

这是 xmltocsharp site 生成的根元素 class:

[XmlRoot(ElementName = "RESPUESTA", Namespace = "http://www.sii.cl/XMLSchema")]
public class RESPUESTA
{
    [XmlElement(ElementName = "RESP_HDR", Namespace = "http://www.sii.cl/XMLSchema")]
    public RESP_HDR RESP_HDR { get; set; }
    [XmlElement(ElementName = "RESP_BODY", Namespace = "http://www.sii.cl/XMLSchema")]
    public RESP_BODY RESP_BODY { get; set; }
    [XmlAttribute(AttributeName = "SII", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string SII { get; set; }
}

问题是 class 无法像之前显示的那样反序列化 XML,但成功了:

<?xml version="1.0" encoding="UTF-8"?>
<RESPUESTA xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SII="http://www.sii.cl/XMLSchema" xmlns="http://www.sii.cl/XMLSchema">
    + <SII:RESP_HDR>
    + <SII:RESP_BODY>
</RESPUESTA>

区别在于命名空间,即使创建对象并将其序列化,结果也是如此。那么,应该在 class 中更改什么以使其与原始 XML 一起使用?

更新:


仔细观察我发现了真正的问题,仍然在根元素中,但我注意到根标签中缺少 xmlns 前缀,我如何在助手中设置它class?

编辑:


这是来自服务响应的 XML 示例:

<?xml version="1.0" encoding="UTF-8"?>
<SII:RESPUESTA xmlns:SII="http://www.sii.cl/XMLSchema">
    <SII:RESP_HDR>
        <SII:ESTADO>0</SII:ESTADO>
        <SII:GLOSA/>
    </SII:RESP_HDR>
    <SII:RESP_BODY>
        <DATOS_CONSULTA>
            <RUT>80182144-3</RUT>
            <TIPO_CONSULTA>DEUDOR</TIPO_CONSULTA>
            <DESDE_DDMMAAAA>01042017</DESDE_DDMMAAAA>
            <HASTA_DDMMAAAA>01052017</HASTA_DDMMAAAA>
        </DATOS_CONSULTA>
        <CESION>
            <VENDEDOR>11455447-9</VENDEDOR>
            <ESTADO_CESION>Cesion Vigente</ESTADO_CESION>
            <DEUDOR>80182144-3</DEUDOR>
            <MAIL_DEUDOR/>
            <TIPO_DOC>33</TIPO_DOC>
            <NOMBRE_DOC>Factura Electronica</NOMBRE_DOC>
            <FOLIO_DOC>107</FOLIO_DOC>
            <FCH_EMIS_DTE>2017-04-04</FCH_EMIS_DTE>
            <MNT_TOTAL>3324860</MNT_TOTAL>
            <CEDENTE>11455447-9</CEDENTE>
            <RZ_CEDENTE>JHON DOE</RZ_CEDENTE>
            <MAIL_CEDENTE>jjdoe@gmail.com</MAIL_CEDENTE>
            <CESIONARIO>762327129-7</CESIONARIO>
            <RZ_CESIONARIO>capital sa</RZ_CESIONARIO>
            <MAIL_CESIONARIO>xcap@capital.com</MAIL_CESIONARIO>
            <FCH_CESION>2017-04-05 13:15</FCH_CESION>
            <MNT_CESION>3324860</MNT_CESION>
            <FCH_VENCIMIENTO>2017-06-04</FCH_VENCIMIENTO>
        </CESION>
        <CESION>
            <VENDEDOR>11455447-9</VENDEDOR>
            <ESTADO_CESION>Cesion Vigente</ESTADO_CESION>
            <DEUDOR>80182144-3</DEUDOR>
            <MAIL_DEUDOR/>
            <TIPO_DOC>33</TIPO_DOC>
            <NOMBRE_DOC>Factura Electronica</NOMBRE_DOC>
            <FOLIO_DOC>34</FOLIO_DOC>
            <FCH_EMIS_DTE>2017-03-01</FCH_EMIS_DTE>
            <MNT_TOTAL>1725500</MNT_TOTAL>
            <CEDENTE>11455447-9</CEDENTE>
            <RZ_CEDENTE>JOE DOE</RZ_CEDENTE>
            <MAIL_CEDENTE>jd@gmail.com</MAIL_CEDENTE>
            <CESIONARIO>762327129-7</CESIONARIO>
            <RZ_CESIONARIO>Capital S.A.</RZ_CESIONARIO>
            <MAIL_CESIONARIO>jcap@capital.com</MAIL_CESIONARIO>
            <FCH_CESION>2017-04-05 17:27</FCH_CESION>
            <MNT_CESION>1725500</MNT_CESION>
            <FCH_VENCIMIENTO>2017-03-01</FCH_VENCIMIENTO>
        </CESION>
    </SII:RESP_BODY>
</SII:RESPUESTA>

到目前为止,我唯一能让它工作的方法是一个非常丑陋的解决方案,这不应该被视为问题的答案!!.

//Query service to obtain XML response
string xmlResponse = siiClient.QueryDocuments(documentsRequest);

//Replace RESPUESTA tags in the XML response, remove the prefix SII
var replacedXML = xmlResponse .Replace("SII:RESPUESTA", "RESPUESTA" );

//Load XML string into XmlDocument
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(replacedXML);

//Add missing namespaces
xDoc.DocumentElement.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
xDoc.DocumentElement.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
xDoc.DocumentElement.SetAttribute("xmlns", "http://www.sii.cl/XMLSchema");

//Now deserialization will work
var documentResponse = xDoc.ParseXML<RESPUESTA>();

理想的解决方案将采用 XML 响应并直接反序列化它,而无需任何预处理,例如:

//Query service to obtain XML response
string xmlResponse = siiClient.QueryDocuments(documentsRequest);

//ParseXML is an extension method, it can handle an string or an XmlDocument
var documentResponse = xmlResponse.ParseXML<RESPUESTA>();

注意:ParseXML是基于@Damian's answer

我拿了你的xml:

<?xml version="1.0" encoding="UTF-8"?>
<SII:RESPUESTA xmlns:SII="http://www.sii.cl/XMLSchema">
  <SII:RESP_HDR/>
  <SII:RESP_BODY/>
</SII:RESPUESTA>

我带你class:

[XmlRoot(ElementName = "RESPUESTA", Namespace = "http://www.sii.cl/XMLSchema")]
public class RESPUESTA
{
    [XmlElement(ElementName = "RESP_HDR", Namespace = "http://www.sii.cl/XMLSchema")]
    public RESP_HDR RESP_HDR { get; set; }
    [XmlElement(ElementName = "RESP_BODY", Namespace = "http://www.sii.cl/XMLSchema")]
    public RESP_BODY RESP_BODY { get; set; }
    [XmlAttribute(AttributeName = "SII", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string SII { get; set; }
}
public class RESP_HDR { }
public class RESP_BODY { }

刚刚添加了两个空 class 存根。

尝试 System.Xml.Serialization.XmlSerializer:

RESPUESTA respuesta;

var xs = new XmlSerializer(typeof(RESPUESTA));

using (var fs = new FileStream("test.xml", FileMode.Open))
    respuesta = (RESPUESTA)xs.Deserialize(fs);

有效!我不明白它如何以及为什么对你不起作用。