反序列化XML

反序列化XML

问题描述:

大家好,

我有一个问题,我无法摆脱.我对WebServices的了解不是很好,我有一个小问题需要解决.
我正在开发Web服务的客户端,但是我无法控制服务器端Web服务(而且我认为它是用Java开发的).我使用WSE3作为我的客户的基础,它似乎可以很好地工作,这对我无法解决的几种方法来说是完全正确的.
根据我的WSDL定义,我生成了代理类,适当的数据类型和要调用的方法.这些方法中的许多返回已反序列化的SOAP消息,并转换为正确的对象类型.不幸的是,其中一些发送回一个ZIP文件的字节数组,其中包含一个格式不正确的xml文件.我设法获取了流,解压缩了文件并读取了xml,但无法正确反序列化xml,然后将其强制转换为相应的类型.这是我的代码的示例,也是我需要反序列化并转换为正确类型的xml的示例.您有什么建议吗?

MyClient客户=新的MyClient(ServiceSettings);
ConnectResponseRetrieveMyType数据;

Hi guys,

I have a problem and I can''t get out of it. My knowledge about WebServices isn''t great and I have a little problem that I need to solve.
I''m developing a client for the web service and I have no power over the server side web service (and I think it is developed in Java). I used WSE3 to base my client on and it seems working pretty fine, exact for a couple of methods, which I can’t solve.
Based on my WSDL definition I generated my proxy classes, whit proper data types and methods to call. Many of these methods return already deserialized SOAP messages, casted to the proper object type. Unfortunately some of them send back a byte array of a ZIP file, containing a not well formatted xml file inside. I managed to get the stream, unzip the file and read the xml, but I can’t deserialize properly the xml and then cast it on a respective type. This is an example of my code, and an example of the xml that I need to deserialize and cast to proper type. Do you have any suggestions?

MyClient client = new MyClient(ServiceSettings);
ConnectResponseRetrieveMyType data;

try
{
	// call web service method
	data = client.syncData(service, startDate, endDate);
	
	// unzip the byte array
	using (ZipFile zip = ZipFile.Read(data.Data))
    {
		if (zip.ContainsEntry("data.xml"))
        {
			List<string> strings = new List<string>();
			
			// read the xml file with multiple root elements
			XmlReaderSettings settings = new XmlReaderSettings();
			settings.ConformanceLevel = ConformanceLevel.Fragment;

			using (XmlReader reader = XmlReader.Create(zip["data.xml"].OpenReader(), settings))
			{
				while (reader.Read())
				{	
					strings.Add(reader.ReadOuterXml());
				}
			}

		}
		else
			return "OGZIP01";
	}
}



最后,我有一个List<>.包含此数据的字符串:



At the end I have an List<> of string containing this data:

<c:CoverDecision TypeOfCover="CreditLimit" CoverId="123123123" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:c="http://atradius.com/connect/_2007_08/" xmlns:o="http://atradius.com/organisation/_2007_08/type/">
    <Buyer>
        <o:Identifier registeredOffice="SYMPH">
            <o:id>123123123</o:id>
            <o:countryTypeIdentifier>AUT</o:countryTypeIdentifier>
        </o:Identifier>
        <o:Identifier registeredOffice="COC">
            <o:id>123123123F</o:id>
            <o:countryTypeIdentifier>AUT</o:countryTypeIdentifier>
        </o:Identifier>
        <o:Name>
            <o:name>SOME GES.M.B.H.</o:name>
            <o:type>REG</o:type>
        </o:Name>
        <o:LegalForm>GMBH</o:LegalForm>
        <o:Address>
            <o:StreetDescription xsi:type="xsd:string">STRAßE 49</o:StreetDescription>
            <o:City>FÜRSTENFELD</o:City>
            <o:PostCode>23123</o:PostCode>
            <o:CountryISOCode>AUT</o:CountryISOCode>
        </o:Address>
    </Buyer>
    <Customer>
        <o:Identifier registeredOffice="SYMPH">
            <o:id>123123</o:id>
            <o:countryTypeIdentifier>NLD</o:countryTypeIdentifier>
        </o:Identifier>
        <o:Identifier registeredOffice="COC">
            <o:id>123123</o:id>
            <o:countryTypeIdentifier>NLD</o:countryTypeIdentifier>
        </o:Identifier>
        <o:Name>
            <o:name>SOME B.V.</o:name>
            <o:type>REG</o:type>
        </o:Name>
    </Customer>
    <PolicyId>123123</PolicyId>
    <GenericApplication>
        <CustomerReference>123123</CustomerReference>
        <EntryDate>2010-02-04</EntryDate>
        <Supersede>false</Supersede>
    </GenericApplication>
    <Decision>
        <ApplicationResult>CreditLimitDecision</ApplicationResult>
        <DecisionDate>2010-02-05</DecisionDate>
        <EffectFrom>2010-02-05</EffectFrom>
        <EffectTo>2010-07-19</EffectTo>
        <CreditLimitDecision>
            <CreditLimitResultCode>APPR</CreditLimitResultCode>
            <DecisionCode>DC16</DecisionCode>
            <FirstAmount>
                <Amount>150000.00</Amount>
                <Conditions>
                    <TypeOfConditions>ADMIN</TypeOfConditions>
                    <ConditionCode>T310</ConditionCode>
                    <ConditionText>Some condition description text.</ConditionText>
                </Conditions>
            </FirstAmount>
            <SecondAmount>
                <Amount>0</Amount>
            </SecondAmount>
        </CreditLimitDecision>
    </Decision>
</c:CoverDecision>




而且我无法反序列化并将其转换为适当的对象类型.我尝试了许多方法,但未成功.也许您有什么建议?

谢谢




And I’m unable to deserialize it and cast it to the proper object type. I tried many approaches but I was unsuccessful. Perhaps you have any suggestion?

Thanks

我没有从您的示例中看到问题.正如我已经说过的,您的示例XML格式正确(您认为不是吗?).可能您需要发布一个从服务接收到的XML样本,该样本格式不正确.您在回答中提到了这种情况.

我可以看到的另一种可能性是您误用了术语.当您说格式不正确的xml文件"时,您是否意味着实际上该文件格式正确但不符合预期的架构?请检查一下.在这种情况下,可能的问题是WSDL错误:例如,您使用的是旧版本,然后使用了服务或类似的东西.这很容易检查.

无论如何,如果您使用Google,就会看到很多相关的讨论:

http://en.lmgtfy.com/?q=%22WSDL-生成的%22 + deserialze +%22C%23%22 [ ^ ].

—SA
I don''t see the problem from you samples. As I already said, your sample XML is well-formed (did you think it is not?). Probably, you need to post a sample of XML received from the service which is not well-formed. You mentioned this case in your answer.

Another possibility I can see is that you misused terminology. When you say "not well formatted xml file", could you mean that in fact the file is well-formed but does not conform to the expected schema? Please check up. If this is the case, the possible problem is WSDL mismath: for example, you use older version then the service or something like that. This is easy to check up.

Anyway you can see a lot of relevant discussions if you Google:

http://en.lmgtfy.com/?q=%22WSDL-generated%22+deserialze+%22C%23%22[^].

—SA


得到答案.坦克一月!
显然,XmlSerializer不知道如何处理名称空间和根元素.

此属性有助于解决问题.

Got the answer. Tanks Jan!
Apparently the XmlSerializer didn''t know how to treat the namespaces and the root element.

This attribute help to solve the problem.

[System.Xml.Serialization.XmlRootAttribute("CoverDecision", Namespace = "http://atradius.com/connect/_2007_08/", IsNullable = false)]
public partial class CoverDecisionType



因此,感谢所有帮助我集思广益的人!



So thanks to all who helped me brainstorming!


可能是我的问题,需要减少工作量.

首先,我尝试以一种标准方式反序列化它:

Probably I''m the problem, need to work less.

First I tried to deserialize it in a standard way:

XmlSerializer serializer = new XmlSerializer(typeof(CoverDecisionType));

CoverDecisionType a = CoverDecisionType)serializer.Deserialize(reader); 



而且我得到了InvalidOperationException({"XML文档(1、2)中存在错误.")
{< CoverDecision xmlns =''http://atradius.com/connect/_2007_08/''>没想到."})

为什么我尝试了这个?我们提供的服务有两种方法.这些方法中有许多是用CoverDecisionType重播的,但不是这种方法,而是用一个字节数组重播的,该字节数组是一个zip文件,其中包含一个带有多个根元素的xml文件.这些元素中的每一个都应该是CoverDecisionType对象. WSE3在WSDL的基础上由WSE3定义CoverDecisionType对象.
但是,现在,在分析返回CoverDecisionType的方法的跟踪信息后,我发现包含在SOAP消息主体中的XML与我列出的代码不同.
由于我不是XML专家,所以我想知道是否可以将该XML反序列化为相同的CoverDecisionType对象.如果没有,最好的方法是什么?

CoverDecisionType定义为(部分):



And I was getting InvalidOperationException ({"There is an error in XML document (1, 2)."}
{"<CoverDecision xmlns=''http://atradius.com/connect/_2007_08/''> was not expected."})

Why I tried this? This we service has a couple of methods. Many of these methods replay with CoverDecisionType, but not this one, this one replays with an byte array that is a zip file, containing an xml file with a multiple root elements. Each of these elements should be CoverDecisionType object. CoverDecisionType object was defined by WSE3 basing the proxy on WSDL.
But, right now, analyzing the trace info of the methods that returns CoverDecisionType, I see that the XML contained into the SOAP message body differs with the code that I listed.
As I''m not an XML expert, I would like to know if it is possible to deserialize this XML into the same CoverDecisionType object. If not, what should be the best way to proceed?

The CoverDecisionType definition is (partial):

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://atradius.com/connect/_2007_08/")]
public partial class CoverDecisionType
{
    private string externalCoverIdField;
    private OrganisationType buyerField;
    private BasicOrganisationType customerField;
    private long policyIdField;
    private BasicRequestSummaryType itemField;
    private ItemChoiceType itemElementNameField;
    private DecisionType decisionField;
    private long coverIdField;
    private CoverType typeOfCoverField;
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string ExternalCoverId
    {
        get
        {
            return this.externalCoverIdField;
        }
        set
        {
            this.externalCoverIdField = value;
        }
    }
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public OrganisationType Buyer
    {
        get
        {
            return this.buyerField;
        }
        set
        {
            this.buyerField = value;
        }
    }
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public BasicOrganisationType Customer
    {
        get
        {
            return this.customerField;
        }
        set
        {
            this.customerField = value;
        }
    }
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public long PolicyId
    {
        get
        {
            return this.policyIdField;
        }
        set
        {
            this.policyIdField = value;
        }
    }
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("CreditCheckApplication", typeof(BasicApplicationSummaryType), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlElementAttribute("CreditLimitApplication", typeof(AmountLimitApplicationSummaryType), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlElementAttribute("GenericApplication", typeof(BasicRequestSummaryType), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlElementAttribute("NoRiskOpinionApplication", typeof(AmountLimitApplicationSummaryType), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlElementAttribute("SpecialProductApplication", typeof(AmountLimitApplicationSummaryType), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")]
    public BasicRequestSummaryType Item
    {
        get
        {
            return this.itemField;
        }
        set
        {
            this.itemField = value;
        }
    }
    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public ItemChoiceType ItemElementName
    {
        get
        {
            return this.itemElementNameField;
        }
        set
        {
            this.itemElementNameField = value;
        }
    }
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public DecisionType Decision
    {
        get
        {
            return this.decisionField;
        }
        set
        {
            this.decisionField = value;
        }
    }
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public long CoverId
    {
        get
        {
            return this.coverIdField;
        }
        set
        {
            this.coverIdField = value;
        }
    }
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public CoverType TypeOfCover
    {
        get
        {
            return this.typeOfCoverField;
        }
        set
        {
            this.typeOfCoverField = value;
        }
    }
}



和正确反序列化的肥皂消息是:



and the soap message that is correctly deserialized is:

<soapenv:body xmlns:soapenv="#unknown">
  <applyforcreditlimitresponse xmlns="http://atradius.com/connect/_2007_08/">
	<coverdecision typeofcover="CreditLimit" coverid="123123">
	  <buyer>
		<ns1:identifier registeredoffice="SYMPH" xmlns:ns1="http://atradius.com/organisation/_2007_08/type/">
		  <ns1:id>123123</ns1:id>
		  <ns1:countrytypeidentifier>NLD</ns1:countrytypeidentifier>
		</ns1:identifier>
		<ns2:identifier registeredoffice="COC" xmlns:ns2="http://atradius.com/organisation/_2007_08/type/">
		  <ns2:id>12312312312</ns2:id>
		  <ns2:countrytypeidentifier>NLD</ns2:countrytypeidentifier>
		</ns2:identifier>
		<ns3:name xmlns:ns3="http://atradius.com/organisation/_2007_08/type/">
		  <ns3:name> BEDRIJVENCONTACTDAGAMSTERDAM</ns3:name>
		  <ns3:type>REG</ns3:type>
		</ns3:name>
		<ns4:legalform xmlns:ns4="http://atradius.com/organisation/_2007_08/type/">STIC</ns4:legalform>
		<ns5:address xmlns:ns5="http://atradius.com/organisation/_2007_08/type/">
		  <ns5:streetdescription>DE 1081-A</ns5:streetdescription>
		  <ns5:city>AMSTERDAM</ns5:city>
		  <ns5:postcode>1081 HV</ns5:postcode>
		  <ns5:countryisocode>NLD</ns5:countryisocode>
		</ns5:address>
	  </buyer>
	  <customer>
		<ns6:identifier registeredoffice="SYMPH" xmlns:ns6="http://atradius.com/organisation/_2007_08/type/">
		  <ns6:id>123123123</ns6:id>
		  <ns6:countrytypeidentifier>NLD</ns6:countrytypeidentifier>
		</ns6:identifier>
		<ns7:identifier registeredoffice="COC" xmlns:ns7="http://atradius.com/organisation/_2007_08/type/">
		  <ns7:id>123123123</ns7:id>
		  <ns7:countrytypeidentifier>NLD</ns7:countrytypeidentifier>
		</ns7:identifier>
		<ns8:name xmlns:ns8="http://atradius.com/organisation/_2007_08/type/">
		  <ns8:name>NL B.V.</ns8:name>
		  <ns8:type>REG</ns8:type>
		</ns8:name>
	  </customer>
	  <policyid>123123</policyid>
	  <creditlimitapplication>
		<customerreference />
		<entrydate>2011-01-20</entrydate>
		<supersede>false</supersede>
		<requestedamount>10000</requestedamount>
		<currencycode>EUR</currencycode>
	  </creditlimitapplication>
	  <decision>
		<applicationresult>ReferedDecision</applicationresult>
		<decisiondate>2011-01-20</decisiondate>
		<effectfrom>2011-01-20</effectfrom>
		<effectto>4712-12-31</effectto>
		<referreddecision xsi:type="ns9:String35" xmlns:ns9="http://atradius.com/organisation/_2007_08/type/" xmlns:xsi="#unknown">REFERRED</referreddecision>
	  </decision>
	</coverdecision>
  </applyforcreditlimitresponse>
</soapenv:body>



有什么建议吗?

谢谢



Any suggestion?

Thanks