我有一個類被序列化爲XML供Web服務使用。在這個類的實例中,XML必須包含CDATA部分以供Web服務讀取,但是我對如何實現這一點不知所措。將類序列化爲XML幷包含CDATA段時的問題
的XML需要看起來像:
<UpdateOrderStatus>
<Action>2</Action>
<Value>
<![CDATA[
<Shipment>
<Header>
<SellerID>
...
]]>
</Value>
</UpdateOrderStatus>
我能夠生成相應的XML,除了CDATA部分。
我的階級結構是這樣的:
public class UpdateOrderStatus
{
public int Action { get; set; }
public ValueInfo Value { get; set; }
public UpdateOrderStatus()
{
Value = new ValueInfo();
}
public class ValueInfo
{
public ShipmentInfo Shipment { get; set; }
public ValueInfo()
{
Shipment = new ShipmentInfo();
}
public class ShipmentInfo
{
public PackageListInfo PackageList { get; set; }
public HeaderInfo Header { get; set; }
public ShipmentInfo()
{
PackageList = new PackageListInfo();
Header = new HeaderInfo();
}
....
我看到的使用提出了一些建議:
[XmlElement("node", typeof(XmlCDataSection))]
但導致異常
我也曾嘗試
[XmlElement("Value" + "<![CDATA[")]
但是生成的XML是不正確顯示
<Value_x003C__x0021__x005B_CDATA_x005B_>
....
</Value_x003C__x0021__x005B_CDATA_x005B_>
誰能告訴我什麼,我做錯了,或者我需要去與此?
- 編輯 -
使每carlosfigueira shipmentInfo序列化工作的大部分,但我得到額外的?在生成的XML字符(請參閱發佈Writing an XML fragment using XmlWriterSettings and XmlSerializer is giving an extra character瞭解詳細信息)
因此我改變了寫XML的方法:
public void WriteXml(XmlWriter writer)
{
using (MemoryStream ms = new MemoryStream())
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Encoding = new UnicodeEncoding(bigEndian: false, byteOrderMark: false);
settings.Indent = true;
using (XmlWriter innerWriter = XmlWriter.Create(ms, settings))
{
shipmentInfoSerializer.Serialize(innerWriter, this.Shipment,ns);
innerWriter.Flush();
writer.WriteCData(Encoding.UTF8.GetString(ms.ToArray()));
}
}
}
但是我沒有得到一個例外:
System.InvalidOperationException: There was an error generating the XML document. ---> System.ArgumentException: '.', hexadecimal
value 0x00, is an invalid character.
- 編輯 -
異常是由於包含我以前的serializeToString方法造成的。由於刪除了CDATA輸出是正確的,除了空格問題,但我也得到了一個名稱空間和xml聲明,應該通過指定的XML設置來刪除它。輸出是:
<?xml version="1.0"?>
<UpdateOrderStatus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Action>1</Action>
<Value><![CDATA[< S h i p m e n t I n f o >
< P a c k a g e L i s t >
< P a c k a g e >
< S h i p D a t e > 2 0 1 2 - 0 7 - 1 3 T 1 1 : 5 8 : 5 1 . 0 9 2 5 6 1 5 - 0 4 : 0 0 </S h i p D a t e >
< I t e m L i s t >
< I t e m >
< S h i p p e d Q t y > 0 </S h i p p e d Q t y >
</I t e m >
</I t e m L i s t >
</P a c k a g e >
</P a c k a g e L i s t >
< H e a d e r >
< S e l l e r I d > S h i p m e n t h e a d e r </S e l l e r I d >
< S O N u m b e r > 0 </S O N u m b e r >
</H e a d e r >
</S h i p m e n t I n f o > ]]></Value>
</UpdateOrderStatus>
任何避免BOM使用新類的想法?
- 編輯3 - SUCCESS!
我已經實現了以下建議的修改,現在有下列作家類和測試方法:
UpdateOrderStatus obj = new UpdateOrderStatus();
obj.Action = 1;
obj.Value = new UpdateOrderStatus.ValueInfo();
obj.Value.Shipment = new UpdateOrderStatus.ValueInfo.ShipmentInfo();
obj.Value.Shipment.Header.SellerId = "Shipment header";
obj.Value.Shipment.PackageList = new UpdateOrderStatus.ValueInfo.ShipmentInfo.PackageListInfo();
obj.Value.Shipment.PackageList.Package = new UpdateOrderStatus.ValueInfo.ShipmentInfo.PackageListInfo.PackageInfo();
obj.Value.Shipment.PackageList.Package.ShipDate = DateTime.Now;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Encoding = new UTF8Encoding(false);
settings.Indent = true;
XmlSerializer xs = new XmlSerializer(typeof(UpdateOrderStatus));
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms, settings);
xs.Serialize(writer, obj, ns);
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
public void WriteXml(XmlWriter writer)
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Indent = true;
StringBuilder sb = new StringBuilder();
using (XmlWriter innerWriter = XmlWriter.Create(sb, settings))
{
shipmentInfoSerializer.Serialize(innerWriter, this.Shipment, ns);
innerWriter.Flush();
writer.WriteCData(sb.ToString());
}
}
這將產生以下XML:
<UpdateOrderStatus>
<Action>1</Action>
<Value><![CDATA[<ShipmentInfo>
<PackageList>
<Package>
<ShipDate>2012-07-13T14:05:36.6170802-04:00</ShipDate>
<ItemList>
<Item>
<ShippedQty>0</ShippedQty>
</Item>
</ItemList>
</Package>
</PackageList>
<Header>
<SellerId>Shipment header</SellerId>
<SONumber>0</SONumber>
</Header>
</ShipmentInfo>]]></Value>
</UpdateOrderStatus>
請注意,CDATA節是一種轉義xml的方式,使其更具可讀性。 CDATA的內容不是Xml。 <![CDATA [ ]]>是<測試/ >的等效如果您是確保內容始終是你應該能夠預先處理文件刪除CDATA有效的XML文檔和反轉義CDATA節的內容。請注意,如果內容無效,Xml將使整個文檔無效。另一個選擇是如下所述實現IXmlSerializable,但一旦啓動它將會增長並且難以維護。 –
Pawel
2012-07-13 16:44:08