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

时间:2017-05-25 21:09:21

标签: c# c#-4.0 xml-serialization xml-deserialization

我使用xmltocsharp site来创建类帮助程序以反序列化特定的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生成的根元素类:

[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; }
}

问题是该类无法像之前显示的那样反序列化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>

不同之处在于命名空间,即使创建对象并将其序列化,这也就是结果。那么,在类中应该更改什么才能使它与原始XML一起使用?

更新

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

修改

这是来自服务响应的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>

2 个答案:

答案 0 :(得分:0)

到目前为止,我能让它发挥作用的唯一方法是使用一个非常难看的解决方案,这不应该被视为问题的答案!!

//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

答案 1 :(得分:0)

我拿了你的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>

我带你去上课:

[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 { }

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

尝试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);

有效!我不明白它是如何以及为什么不适合你。