我有一个肥皂消息如下所示。我想只获取request元素及其子节点。
<?xml version="1.0" encoding="UTF-8" ?>
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:header>
<htngheader xmlns="http://htng.org/1.1/Header/">
<From>
<systemId>abc</systemId>
<address>abc/rm12.12</address>
<Credential>
<userName>xyz002</userName>
<password>xyz002</password>
</Credential>
</From>
<To>
<systemID>PMM1</systemID>
</To>
<timeStamp>2009-04-23T10:59:00-04:00</timeStamp>
<echoToken>9715f855-bd64-8e3e-905b-aa7ff227af2f</echoToken>
<transactionId>760873954047</transactionId>
<action>Request</action>
</htngheader>
</soap:header>
<soap:body>
<OTA_HotelInvCountNotifRQ echotoken="8c26af40-d777-a21b-ec7e-8d4a8d548a2d"
timestamp="2011-04-23T10:59:00-04:00"
target="Production"
version="1.002" sequencenmbr="760871059"
xmlns="http://www.example.com/OTA/2003/05"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Inventories HotelCode="ILP002"
HotelName="Blue Lagoon Suites">
<Inventory>
<StatusApplicationControl Start="2011-08-03" End="2011-08-03"
InvTypeCode="QU" Override="true"/>
<InvCounts>
<InvCount CountType="1" Count="0"/>
</InvCounts>
</Inventory>
</Inventories>
</OTA_HotelInvCountNotifRQ>
</soap:body>
</soap:envelope>
当我尝试反序列化上面的消息时,它会给我以下异常:
发生了'System.InvalidOperationException'类型的异常 System.Xml.dll但未在用户代码中处理
其他信息:XML文档中存在错误(2,2)。
这是我的Deserealize方法:
private OTA_HotelInvCountNotifRQ DeserializeResXMl(string xmlbody)
{
OTA_HotelInvCountNotifRQ ret = null;
if (xmlbody != null && xmlbody != string.Empty)
{
try
{
long TimeStart = DateTime.Now.Ticks;
XmlSerializer serializer;
serializer = new XmlSerializer(typeof(OTA_HotelInvCountNotifRQ));
ret = (OTA_HotelInvCountNotifRQ)serializer.Deserialize(new StringReader(xmlbody));
}
catch (Exception e)
{
ret = null;
}
}
return ret;
}
代码更新:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.example.org/OTA/2003/05")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.opentravel.org/OTA/2003/05", IsNullable = false)]
public partial class OTA_HotelInvCountNotifRQ
{
private InvCountType inventoriesField;
private string echoTokenField;
private System.DateTime timeStampField;
private OTA_HotelInvCountNotifRQTarget targetField;
private decimal versionField;
public OTA_HotelInvCountNotifRQ()
{
this.targetField = OTA_HotelInvCountNotifRQTarget.Production;
}
/// <remarks/>
public InvCountType Inventories
{
get
{
return this.inventoriesField;
}
set
{
this.inventoriesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string EchoToken
{
get
{
return this.echoTokenField;
}
set
{
this.echoTokenField = value;
}
}
}
我该如何解决这个问题?
答案 0 :(得分:0)
尝试以下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
try
{
OTA_HotelInvCountNotifRQ ota_HotelInvCountNotifRQ = new OTA_HotelInvCountNotifRQ();
string envelope = File.ReadAllText(FILENAME);
OTA_HotelInvCountNotifRQ serializedData = ota_HotelInvCountNotifRQ.DeserializeResXMl(envelope);
}
catch (Exception e)
{
string message = e.Message;
string stacktrace = e.StackTrace;
}
}
}
[XmlRoot( ElementName = "envelope")]
public class Envelope
{
[XmlElement(ElementName = "body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Body body { get; set; }
}
[XmlRoot(ElementName = "body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Body
{
[XmlElement(ElementName = "OTA_HotelInvCountNotifRQ", Namespace = "http://www.example.com/OTA/2003/05")]
public OTA_HotelInvCountNotifRQ ota_HotelInvCountNotifRQ { get; set; }
}
[XmlRoot(ElementName = "OTA_HotelInvCountNotifRQ", Namespace = "http://www.example.com/OTA/2003/05")]
public partial class OTA_HotelInvCountNotifRQ
{
private InvCountType inventoriesField;
private string echoTokenField;
private System.DateTime timeStampField;
private OTA_HotelInvCountNotifRQTarget targetField;
private decimal versionField;
public OTA_HotelInvCountNotifRQ()
{
this.targetField = OTA_HotelInvCountNotifRQTarget.Production;
}
/// <remarks/>
public InvCountType Inventories
{
get
{
return this.inventoriesField;
}
set
{
this.inventoriesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string EchoToken
{
get
{
return this.echoTokenField;
}
set
{
this.echoTokenField = value;
}
}
public OTA_HotelInvCountNotifRQ DeserializeResXMl(string envelopeStr)
{
OTA_HotelInvCountNotifRQ ret = null;
if (envelopeStr != null && envelopeStr != string.Empty)
{
try
{
long TimeStart = DateTime.Now.Ticks;
XmlSerializer serializer;
//serializer = new XmlSerializer(typeof(OTA_HotelInvCountNotifRQ));
serializer = new XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(new StringReader(envelopeStr));
ret = envelope.body.ota_HotelInvCountNotifRQ;
}
catch (Exception e)
{
ret = null;
}
}
return ret;
}
}
public class InvCountType
{
}
public class OTA_HotelInvCountNotifRQTarget
{
public static OTA_HotelInvCountNotifRQTarget Production { get; set; }
}
}
我对xml进行了一些更改
<?xml version="1.0" encoding="UTF-8" ?>
<envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:header>
<htngheader xmlns="http://htng.org/1.1/Header/">
<From>
<systemId>abc</systemId>
<address>abc/rm12.12</address>
<Credential>
<userName>xyz002</userName>
<password>xyz002</password>
</Credential>
</From>
<To>
<systemID>PMM1</systemID>
</To>
<timeStamp>2009-04-23T10:59:00-04:00</timeStamp>
<echoToken>9715f855-bd64-8e3e-905b-aa7ff227af2f</echoToken>
<transactionId>760873954047</transactionId>
<action>Request</action>
</htngheader>
</soap:header>
<soap:body>
<OTA_HotelInvCountNotifRQ echotoken="8c26af40-d777-a21b-ec7e-8d4a8d548a2d"
timestamp="2011-04-23T10:59:00-04:00"
target="Production"
version="1.002" sequencenmbr="760871059"
xmlns="http://www.example.com/OTA/2003/05"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Inventories HotelCode="ILP002"
HotelName="Blue Lagoon Suites">
<Inventory>
<StatusApplicationControl Start="2011-08-03" End="2011-08-03"
InvTypeCode="QU" Override="true"/>
<InvCounts>
<InvCount CountType="1" Count="0"/>
</InvCounts>
</Inventory>
</Inventories>
</OTA_HotelInvCountNotifRQ>
</soap:body>
</envelope>
答案 1 :(得分:0)
以下是使用XML Linq的解决方案
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var ota_HotelInvCountNotifRQ = doc.Descendants().Where(x => x.Name.LocalName == "OTA_HotelInvCountNotifRQ").Select(y => new OTA_HotelInvCountNotifRQ()
{
echotoken = (string)y.Attribute("echotoken"),
timeStampField = DateTime.Parse((string)y.Attribute("timestamp")),
versionField = (decimal)y.Attribute("version"),
sequencenmbr = (int)y.Attribute("sequencenmbr"),
hotelCode = (string)y.Descendants().Where(z => z.Name.LocalName == "Inventories").FirstOrDefault().Attribute("HotelCode"),
hotelName = (string)y.Descendants().Where(z => z.Name.LocalName == "Inventories").FirstOrDefault().Attribute("HotelName"),
start = (DateTime)y.Descendants().Where(z => z.Name.LocalName == "StatusApplicationControl").FirstOrDefault().Attribute("Start"),
end = (DateTime)y.Descendants().Where(z => z.Name.LocalName == "StatusApplicationControl").FirstOrDefault().Attribute("End"),
invTypeCode = (string)y.Descendants().Where(z => z.Name.LocalName == "StatusApplicationControl").FirstOrDefault().Attribute("InvTypeCode"),
_override = (Boolean)y.Descendants().Where(z => z.Name.LocalName == "StatusApplicationControl").FirstOrDefault().Attribute("Override"),
countType = (int)y.Descendants().Where(z => z.Name.LocalName == "InvCount").FirstOrDefault().Attribute("CountType"),
count = (int)y.Descendants().Where(z => z.Name.LocalName == "InvCount").FirstOrDefault().Attribute("Count"),
}).FirstOrDefault();
}
}
public class OTA_HotelInvCountNotifRQ
{
public string echotoken { get; set; }
public DateTime timeStampField { get; set; }
public decimal versionField { get; set; }
public int sequencenmbr { get; set; }
public string hotelCode { get; set; }
public string hotelName { get; set; }
public DateTime start { get; set; }
public DateTime end { get; set; }
public string invTypeCode { get; set; }
public Boolean _override { get; set; }
public int count { get; set; }
public int countType { get; set; }
}
}
答案 2 :(得分:0)
我试图使用以下结构反序列化XML:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<GetCategoryFeaturesResponse xmlns="urn:ebay:apis:eBLBaseComponents">
[...]
</GetCategoryFeaturesResponse>
</soapenv:Body>
</soapenv:Envelope>
问题似乎是xmlns声明,导致XmlSerializer导致所描述的错误。
我添加了一个XmlRootAttribute作为构造函数的参数,并删除了不需要的元素。可能不是最干净但快速的解决方案。
public GetCategoryFeaturesResponseType GetCategoryFeatures(int categoryId)
{
var apiCall = new GetCategoryFeaturesCall(ApiContext)
{
CategoryID = categoryId.ToString()
};
try
{
apiCall.GetCategoryFeatures();
}
catch (Exception e)
{
return null;
}
var response = apiCall.SoapResponse;
if (response == null)
return null;
response = TrimXml(response, "<GetCategoryFeaturesResponse xmlns=\"urn:ebay:apis:eBLBaseComponents\">",
"</GetCategoryFeaturesResponse>");
var responseStream = Helpers.Serialization.CreateStream(response);
var rootAttribute = new XmlRootAttribute()
{
ElementName = "GetCategoryFeaturesResponse",
Namespace = "urn:ebay:apis:eBLBaseComponents",
IsNullable = true
};
GetCategoryFeaturesResponseType categoryFeatures;
try
{
categoryFeatures =
Helpers.Serialization.SerializeToModel<GetCategoryFeaturesResponseType>(responseStream,
rootAttribute);
}
catch (Exception e)
{
return null;
}
return categoryFeatures;
}
private static string TrimXml(string origin, string begin, string end)
{
var startIndex = origin.IndexOf(begin, StringComparison.Ordinal);
var endLength = origin.IndexOf(end, StringComparison.Ordinal);
endLength = endLength - startIndex + end.Length;
return origin.Substring(startIndex, endLength);
}