问题序列化类XML和包括CDATA节 [英] Problems serializing a class to XML and including a CDATA section
问题描述
我有一个是通过Web服务序列化为XML消费类。在这一类实例的XML必须包含CDATA部分Web服务读它,但我就如何实现这一损失。
XML的需要看这样的:
< UpdateOrderStatus>
<作用> 2'; /作用>
< VALUE>
<![CDATA [
<装运>
<页眉和GT;
< SellerID>
...
]]≥
< /价值与GT;
< / UpdateOrderStatus>
我能够生成相应的XML,除了CDATA部分。
我的阶级结构是这样的:
公共类UpdateOrderStatus
{
公众诠释行动{搞定;组; }
公共ValueInfo值{搞定;组; }
公共UpdateOrderStatus()
{
值=新ValueInfo();
}
公共类ValueInfo
{
公共ShipmentInfo出货{搞定;组; }
公共ValueInfo()
{
出货=新ShipmentInfo();
}
公共类ShipmentInfo
{
公共PackageListInfo PackageList {搞定;组; }
公共HeaderInfo头{搞定;组; }
公共ShipmentInfo()
{
PackageList =新PackageListInfo();
=头新HeaderInfo();
}
....
我已经看到了一些使用建议:
[的XmlElement(节点的typeof(XmlCDataSection))]
但导致异常
我也试过
[的XmlElement(值+<![CDATA [)]
但生成的XML是不正确的表现。
< Value_x003C__x0021__x005B_CDATA_x005B_>
....
< / Value_x003C__x0021__x005B_CDATA_x005B_>
谁能告诉我什么我做错了,或者我需要去与此?
- Edit--
使得每carlosfigueira shipmentInfo序列工作的大部分,但我得到额外?在生成的XML字符(看帖子编写使用XmlWriterSettings和XmlSerializer的是给了细节的额外字符)
XML片段
因此,我改变了写XML的方法:
公共无效中WriteXML(XmlWriter的作家)使用
{
(MemoryStream的毫秒=新的MemoryStream())
{
XmlSerializerNamespaces NS =新XmlSerializerNamespaces();
ns.Add(,);
XmlWriterSettings设置=新XmlWriterSettings();
settings.OmitXmlDeclaration = TRUE;
settings.Encoding =新UnicodeEncoding(大尾端:假的,byteOrderMark:假);
settings.Indent = TRUE;使用(XmlWriter的innerWriter = XmlWriter.Create(MS,设置))
{
shipmentInfoSerializer.Serialize(innerWriter,this.Shipment,NS)
;
innerWriter.Flush();
writer.WriteCData(Encoding.UTF8.GetString(ms.ToArray()));
}
}
}
不过我没有得到一个例外:
System.InvalidOperationException:有一个错误生成XML文档。 ---> System.ArgumentException:'',十六进制
值为0x00,是一个无效字符。
- 编辑 -
的
例外被列入我以前serializeToString方法造成的。由于去掉了CDATA输出是正确的,除了间距的问题,但我也越来越应由指定的XML设置中删除一个命名空间和XML声明。输出是:
< XML版本=1.0>?
< UpdateOrderStatus的xmlns:XSI =http://www.w3.org/2001/XMLSchema-instance的xmlns:XSD =http://www.w3.org/2001/XMLSchema>
<作用> 1 LT; /作用>
< VALUE><![CDATA [<中文I P M E N t个我N·O>
< P上C k的A GÉ左I S T>
< P上C k的A G e基
<中文我P(D)的T e基2 0 1 2 - 0 7 - 1 3个T 1:5 8 5 1。 0 9 2 5 6 1 5 - 0 4 0 0℃; / S H I P(D)的T e基
<我T E M L I S T>
<我T E M>
<中文I P p E D Q T中Y'GT; 0℃; / S ^ h I P p E D Q T中Y'GT;
< / I T E M>
< / I T E M L I S T>
< / P C k的A G e基
< / P C k的A GÉ左I S T>
< ^ hË一个D E R>
<发E L LËR I D>中文I P M E N t个^ hË一个D E为r / SÉ左L E R I D>
< S 0 N个U M BèR> 0℃; / S 0 N个U M BèR>
< / HË一个D E R>
< / S H I P M简T I·N·O> ]]>< /价值与GT;
< / UpdateOrderStatus>
使用新的类避免了BOM的任何想法?
-
建议
我已经实现变化的成功 - 编辑3!以下,现在有以下Writer类和测试方法:
UpdateOrderStatus的obj =新UpdateOrderStatus();
obj.Action = 1;
obj.Value =新UpdateOrderStatus.ValueInfo();
obj.Value.Shipment =新UpdateOrderStatus.ValueInfo.ShipmentInfo();
obj.Value.Shipment.Header.SellerId =装运头;
obj.Value.Shipment.PackageList =新UpdateOrderStatus.ValueInfo.ShipmentInfo.PackageListInfo();
obj.Value.Shipment.PackageList.Package =新UpdateOrderStatus.ValueInfo.ShipmentInfo.PackageListInfo.PackageInfo();
obj.Value.Shipment.PackageList.Package.ShipDate = DateTime.Now;
XmlSerializerNamespaces NS =新XmlSerializerNamespaces();
ns.Add(,);
XmlWriterSettings设置=新XmlWriterSettings();
settings.OmitXmlDeclaration = TRUE;
settings.Encoding =新的UTF8Encoding(假);
settings.Indent = TRUE;
XmlSerializer的XS =新的XmlSerializer(typeof运算(UpdateOrderStatus));
的MemoryStream毫秒=新的MemoryStream();
XmlWriter的作家= XmlWriter.Create(MS,设置);
xs.Serialize(作家,OBJ,NS);
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
公共无效中WriteXML(XmlWriter的作家)
{
XmlSerializerNamespaces NS =新XmlSerializerNamespaces();
ns.Add(,);
XmlWriterSettings设置=新XmlWriterSettings();
settings.OmitXmlDeclaration = TRUE;
settings.Indent = TRUE;
StringBuilder的SB =新的StringBuilder();
使用(XmlWriter的innerWriter = XmlWriter.Create(SB,设置))
{
shipmentInfoSerializer.Serialize(innerWriter,this.Shipment,NS);
innerWriter.Flush();
writer.WriteCData(sb.ToString());
}
}
这将产生以下XML:
< UpdateOrderStatus>
<作用> 1 LT; /作用>
< VALUE><![CDATA [< ShipmentInfo>
< PackageList>
<包装及GT;
<&并按ShipDate GT; 2012-07-13T14:05:36.6170802-04:00< /并按ShipDate>
<&ITEMLIST GT;
<项目>
将; ShippedQty大于0&下; / ShippedQty>
< /项目>
< / ITEMLIST>
< /包装及GT;
< / PackageList>
<页眉和GT;
< SellerId>装运头< / SellerId>
将; SONumber大于0&下; / SONumber>
< /页眉和GT;
< / ShipmentInfo>]]>< /价值与GT;
< / UpdateOrderStatus>
在回应'空间'你以后看到您的编辑,这是因为编码您使用的是(Unicode中,每个字符2个字节)。
尝试:
settings.Encoding =新Utf8Encoding(假) ;
编辑:
另外,还要注意的是格式的MemoryStream
是的不的一定是有效的UTF-8编码的字符串!您可以使用的StringBuilder
而不是的MemoryStream
以创建你内心的作家。
公共无效中WriteXML(XmlWriter的作家)
{
XmlSerializerNamespaces NS =新XmlSerializerNamespaces();
ns.Add(,);
XmlWriterSettings设置=新XmlWriterSettings();
settings.OmitXmlDeclaration = TRUE;
settings.Indent = TRUE;
StringBuilder的SB =新的StringBuilder();
使用(XmlWriter的innerWriter = XmlWriter.Create(SB,设置))
{
shipmentInfoSerializer.Serialize(innerWriter,this.Shipment,NS);
innerWriter.Flush();
writer.WriteCData(sb.ToString());
}
}
I have a class that is serialized into XML for consumption by a web service. In this classes instance the XML must include a CDATA section for the web service to read it but I am at a loss on how to implement this.
The XML needs to look like:
<UpdateOrderStatus>
<Action>2</Action>
<Value>
<![CDATA[
<Shipment>
<Header>
<SellerID>
...
]]>
</Value>
</UpdateOrderStatus>
I am able to generate the appropriate XML, except for the CDATA part.
My class structure looks like:
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();
}
....
I have seen some suggestions on using:
[XmlElement("node", typeof(XmlCDataSection))]
but that causes an exception
I have also tried
[XmlElement("Value" + "<![CDATA[")]
but the resulting XML is incorrect showing
<Value_x003C__x0021__x005B_CDATA_x005B_>
....
</Value_x003C__x0021__x005B_CDATA_x005B_>
Can anyone show me what I am doing wrong, or where I need to go with this?
--Edit--
making shipmentInfo serializable per carlosfigueira works for the most part, however I get extra ? characters in the resulting XML ( see post Writing an XML fragment using XmlWriterSettings and XmlSerializer is giving an extra character for details )
As such I changed the Write XML method to:
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()));
}
}
}
However I am not getting an exception:
System.InvalidOperationException: There was an error generating the XML document. ---> System.ArgumentException: '.', hexadecimal
value 0x00, is an invalid character.
--Edit --
The exception was caused by the inclusion of my previous serializeToString method. Since removing that the CDATA output is correct, except for a spacing issue, but I am also getting a namespace and xml declaration that should be removed by the XML settings specified. Output is:
<?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>
Any ideas of avoiding the BOM using the new class?
--Edit 3 -- SUCCESS!
I have implemented changes suggested below and now have the following writer class and test methods:
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());
}
}
This produces the following 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>
In response to the 'spaces' you are seeing after your edit, it is because of the encoding you are using (Unicode, 2 bytes per character).
Try:
settings.Encoding = new Utf8Encoding(false);
EDIT:
Also, note that format of the MemoryStream
is not necessarily a valid UTF-8 encoded string! You can use a StringBuilder
instead of MemoryStream
to create your inner writer.
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和包括CDATA节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!