C# 将类序列化为XML并包含CDATA节时出现问题
我有一个被序列化为XML的类,供web服务使用。在这个类实例中,XML必须包含一个CDATA部分,web服务才能读取它,但我不知道如何实现它 XML需要如下所示:C# 将类序列化为XML并包含CDATA节时出现问题,c#,xml,xml-serialization,C#,Xml,Xml Serialization,我有一个被序列化为XML的类,供web服务使用。在这个类实例中,XML必须包含一个CDATA部分,web服务才能读取它,但我不知道如何实现它 XML需要如下所示: <UpdateOrderStatus> <Action>2</Action> <Value> <![CDATA[ <Shipment> &l
<UpdateOrderStatus>
<Action>2</Action>
<Value>
<![CDATA[
<Shipment>
<Header>
<SellerID>
...
]]>
</Value>
</UpdateOrderStatus>
我看到了一些关于使用的建议:
[XmlElement("node", typeof(XmlCDataSection))]
但这导致了一个例外
我也试过了
[XmlElement("Value" + "<![CDATA[")]
然而,我没有得到一个例外:
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>
这将生成以下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>
1.
2012-07-13T14:05:36.6170802-04:00
0
装运头
0
]]>
这有什么帮助吗:
另外,使用该属性时出现了什么异常
--编辑--
您可以尝试添加自定义类,并执行以下操作:
some xml serializable class,
{
.......
[XmlElement("PayLoad", Type=typeof(CDATA))]
public CDATA PayLoad
{
get { return _payLoad; }
set { _payLoad = value; }
}
}
public class CDATA : IXmlSerializable
{
private string text;
public CDATA()
{}
public CDATA(string text)
{
this.text = text;
}
public string Text
{
get { return text; }
}
/// <summary>
/// Interface implementation not used here.
/// </summary>
XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
/// <summary>
/// Interface implementation, which reads the content of the CDATA tag
/// </summary>
void IXmlSerializable.ReadXml(XmlReader reader)
{
this.text = reader.ReadElementString();
}
/// <summary>
/// Interface implementation, which writes the CDATA tag to the xml
/// </summary>
void IXmlSerializable.WriteXml(XmlWriter writer)
{
writer.WriteCData(this.text);
}
}
一些xml可序列化类,
{
.......
[XmlElement(“有效负载”,类型=类型(CDATA))]
公共CDATA有效负载
{
获取{return\u payLoad;}
设置{u payLoad=value;}
}
}
公共类CDATA:IXmlSerializable
{
私有字符串文本;
公共CDATA()
{}
公共CDATA(字符串文本)
{
this.text=文本;
}
公共字符串文本
{
获取{返回文本;}
}
///
///此处未使用接口实现。
///
XmlSchema IXmlSerializable.GetSchema()
{
返回null;
}
///
///接口实现,它读取CDATA标记的内容
///
void IXmlSerializable.ReadXml(XmlReader)
{
this.text=reader.ReadElementString();
}
///
///接口实现,将CDATA标记写入xml
///
void IXmlSerializable.WriteXml(XmlWriter编写器)
{
WriteCData(this.text);
}
}
如图所示将ShipmentInfo实现为
IXmlSerializable
类型将接近您所需要的-请参见下面的示例
public class StackOverflow_11471676
{
public class UpdateOrderStatus
{
public int Action { get; set; }
public ValueInfo Value { get; set; }
}
[XmlType(TypeName = "Shipment")]
public class ShipmentInfo
{
public string Header { get; set; }
public string Body { get; set; }
}
public class ValueInfo : IXmlSerializable
{
public ShipmentInfo Shipment { get; set; }
private XmlSerializer shipmentInfoSerializer = new XmlSerializer(typeof(ShipmentInfo));
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
using (MemoryStream ms = new MemoryStream(
Encoding.UTF8.GetBytes(
reader.ReadContentAsString())))
{
Shipment = (ShipmentInfo)this.shipmentInfoSerializer.Deserialize(ms);
}
}
public void WriteXml(XmlWriter writer)
{
using (MemoryStream ms = new MemoryStream())
{
using (XmlWriter innerWriter = XmlWriter.Create(ms, new XmlWriterSettings { OmitXmlDeclaration = true }))
{
shipmentInfoSerializer.Serialize(innerWriter, this.Shipment);
innerWriter.Flush();
writer.WriteCData(Encoding.UTF8.GetString(ms.ToArray()));
}
}
}
}
public static void Test()
{
UpdateOrderStatus obj = new UpdateOrderStatus
{
Action = 1,
Value = new ValueInfo
{
Shipment = new ShipmentInfo
{
Header = "Shipment header",
Body = "Shipment body"
}
}
};
XmlSerializer xs = new XmlSerializer(typeof(UpdateOrderStatus));
MemoryStream ms = new MemoryStream();
xs.Serialize(ms, obj);
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
}
对于编辑后看到的“空格”,这是因为您使用的编码(Unicode,每个字符2个字节) 尝试: 编辑: 另外,请注意,
MemoryStream
的格式不一定是有效的UTF-8编码字符串!您可以使用StringBuilder
而不是MemoryStream
来创建内部编写器
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());
}
}
我认为卡洛斯菲盖拉只是给出了一个优雅的回答,但乍一看可能有点难以理解。这里有一个供您考虑的替代方案,您可以分别序列化/反序列化
UpdateOrderStatus
和ShipmentInfo
将业务对象类定义为:
[XmlRoot("UpdateOrderStatus")]
public class UpdateOrderStatus
{
[XmlElement("Action")]
public int Action { get; set; }
private String valueField;
[XmlElement("Value")]
public XmlCDataSection Value
{
get
{
XmlDocument xmlDoc = new XmlDocument();
return xmlDoc.CreateCDataSection(valueField);
}
set
{
this.valueField = value.Value;
}
}
[XmlIgnore]
public ShipmentInfo Shipment
{
get;
set;
}
}
[XmlRoot("ShipmentInfo")]
public class ShipmentInfo
{
[XmlElement("Package")]
public String Package { get; set; }
[XmlElement("Header")]
public String Header { get; set; }
}
请注意,对于值
字段,应使用xmlcatasection
。
以下是测试/辅助功能:
// Test function
const string t = @"<UpdateOrderStatus>
<Action>2</Action>
<Value>
<![CDATA[<ShipmentInfo>
<Package>packageInfo</Package>
<Header>headerInfo</Header>
</ShipmentInfo>]]>
</Value>
</UpdateOrderStatus>";
static void Test1()
{
UpdateOrderStatus os = Deserialize(t);
String t2 = XmlUtil.Serialize(os);
}
// Helper functions
static UpdateOrderStatus Deserialize(String str)
{
UpdateOrderStatus os = XmlUtil.DeserializeString<UpdateOrderStatus>(str);
os.Shipment = XmlUtil.DeserializeString<ShipmentInfo>(os.Value.InnerText);
return os;
}
public static class XmlUtil
{
public static String Serialize<T>(T o)
{
XmlSerializer s = new XmlSerializer(typeof(T)); //, overrides);
//StringBuilder builder = new StringBuilder();
MemoryStream ms = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.Indent = true;
using (XmlWriter xmlWriter = XmlWriter.Create(ms, settings))
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(String.Empty, String.Empty);
s.Serialize(xmlWriter, o, ns);
}
Byte[] bytes = ms.ToArray();
// discard the BOM part
Int32 idx = settings.Encoding.GetPreamble().Length;
return Encoding.UTF8.GetString(bytes, idx, bytes.Length - idx);
}
public static T DeserializeString<T>(String content)
{
using (TextReader reader = new StringReader(content))
{
XmlSerializer s = new XmlSerializer(typeof(T));
return (T)s.Deserialize(reader);
}
}
...
}
//测试函数
常量字符串t=@“
2.
包装信息
校长信息
]]>
";
静态void Test1()
{
UpdateOrderStatus os=反序列化(t);
字符串t2=XmlUtil.Serialize(os);
}
//辅助函数
静态UpdateOrderStatus反序列化(字符串str)
{
UpdateOrderStatus os=XmlUtil.DeserializeString(str);
os.shipping=XmlUtil.DeserializeString(os.Value.InnerText);
返回操作系统;
}
公共静态类XmlUtil
{
公共静态字符串序列化(TO)
{
XmlSerializer s=新的XmlSerializer(typeof(T));/,重写);
//StringBuilder=新的StringBuilder();
MemoryStream ms=新的MemoryStream();
XmlWriterSettings=新的XmlWriterSettings();
settings.Encoding=Encoding.UTF8;
settings.Indent=true;
使用(XmlWriter=XmlWriter.Create(ms,设置))
{
XmlSerializerNamespaces ns=新的XmlSerializerNamespaces();
ns.Add(String.Empty,String.Empty);
s、 序列化(xmlWriter,o,ns);
}
Byte[]bytes=ms.ToArray();
//放弃BOM表零件
Int32 idx=settings.Encoding.getPremission().Length;
返回Encoding.UTF8.GetString(bytes,idx,bytes.Length-idx);
}
公共静态T反序列化字符串(字符串内容)
{
使用(TextReader=新的StringReader(内容))
{
XmlSerializer s=新的XmlSerializer(typeof(T));
返回(T)s.反序列化(读取器);
}
}
...
}
下面的示例仅在定义了架构的结构并且您没有选择修改架构时出现
反序列化/序列化[xmltext]值时,很难将文本保存在CDATA[]
随函附上您可以使用compiletransform按原样获取xml
中的CDATA
值,但是CDATA
一旦在C中反序列化并加载到内存中就会丢失
这是最简单的方法之一
CDATA
嵌入test1值string xml=“@##@!#!#!@#!@%$%@#$%#;
xns=@;
XDocument doc=XDocument.Parse(xml);
string xmlString=string.Empty;
var coll=来自文档子体中的查询(ns+“test1”)
选择查询;
foreach(coll中的var值){
ReplaceNodes(新的XCData(value.value));
}
doc.save(“test.xml”);//将doc.tostring转换为(
some xml serializable class,
{
.......
[XmlElement("PayLoad", Type=typeof(CDATA))]
public CDATA PayLoad
{
get { return _payLoad; }
set { _payLoad = value; }
}
}
public class CDATA : IXmlSerializable
{
private string text;
public CDATA()
{}
public CDATA(string text)
{
this.text = text;
}
public string Text
{
get { return text; }
}
/// <summary>
/// Interface implementation not used here.
/// </summary>
XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
/// <summary>
/// Interface implementation, which reads the content of the CDATA tag
/// </summary>
void IXmlSerializable.ReadXml(XmlReader reader)
{
this.text = reader.ReadElementString();
}
/// <summary>
/// Interface implementation, which writes the CDATA tag to the xml
/// </summary>
void IXmlSerializable.WriteXml(XmlWriter writer)
{
writer.WriteCData(this.text);
}
}
public class StackOverflow_11471676
{
public class UpdateOrderStatus
{
public int Action { get; set; }
public ValueInfo Value { get; set; }
}
[XmlType(TypeName = "Shipment")]
public class ShipmentInfo
{
public string Header { get; set; }
public string Body { get; set; }
}
public class ValueInfo : IXmlSerializable
{
public ShipmentInfo Shipment { get; set; }
private XmlSerializer shipmentInfoSerializer = new XmlSerializer(typeof(ShipmentInfo));
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
using (MemoryStream ms = new MemoryStream(
Encoding.UTF8.GetBytes(
reader.ReadContentAsString())))
{
Shipment = (ShipmentInfo)this.shipmentInfoSerializer.Deserialize(ms);
}
}
public void WriteXml(XmlWriter writer)
{
using (MemoryStream ms = new MemoryStream())
{
using (XmlWriter innerWriter = XmlWriter.Create(ms, new XmlWriterSettings { OmitXmlDeclaration = true }))
{
shipmentInfoSerializer.Serialize(innerWriter, this.Shipment);
innerWriter.Flush();
writer.WriteCData(Encoding.UTF8.GetString(ms.ToArray()));
}
}
}
}
public static void Test()
{
UpdateOrderStatus obj = new UpdateOrderStatus
{
Action = 1,
Value = new ValueInfo
{
Shipment = new ShipmentInfo
{
Header = "Shipment header",
Body = "Shipment body"
}
}
};
XmlSerializer xs = new XmlSerializer(typeof(UpdateOrderStatus));
MemoryStream ms = new MemoryStream();
xs.Serialize(ms, obj);
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
}
settings.Encoding = new Utf8Encoding(false);
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());
}
}
[XmlRoot("UpdateOrderStatus")]
public class UpdateOrderStatus
{
[XmlElement("Action")]
public int Action { get; set; }
private String valueField;
[XmlElement("Value")]
public XmlCDataSection Value
{
get
{
XmlDocument xmlDoc = new XmlDocument();
return xmlDoc.CreateCDataSection(valueField);
}
set
{
this.valueField = value.Value;
}
}
[XmlIgnore]
public ShipmentInfo Shipment
{
get;
set;
}
}
[XmlRoot("ShipmentInfo")]
public class ShipmentInfo
{
[XmlElement("Package")]
public String Package { get; set; }
[XmlElement("Header")]
public String Header { get; set; }
}
// Test function
const string t = @"<UpdateOrderStatus>
<Action>2</Action>
<Value>
<![CDATA[<ShipmentInfo>
<Package>packageInfo</Package>
<Header>headerInfo</Header>
</ShipmentInfo>]]>
</Value>
</UpdateOrderStatus>";
static void Test1()
{
UpdateOrderStatus os = Deserialize(t);
String t2 = XmlUtil.Serialize(os);
}
// Helper functions
static UpdateOrderStatus Deserialize(String str)
{
UpdateOrderStatus os = XmlUtil.DeserializeString<UpdateOrderStatus>(str);
os.Shipment = XmlUtil.DeserializeString<ShipmentInfo>(os.Value.InnerText);
return os;
}
public static class XmlUtil
{
public static String Serialize<T>(T o)
{
XmlSerializer s = new XmlSerializer(typeof(T)); //, overrides);
//StringBuilder builder = new StringBuilder();
MemoryStream ms = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.Indent = true;
using (XmlWriter xmlWriter = XmlWriter.Create(ms, settings))
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(String.Empty, String.Empty);
s.Serialize(xmlWriter, o, ns);
}
Byte[] bytes = ms.ToArray();
// discard the BOM part
Int32 idx = settings.Encoding.GetPreamble().Length;
return Encoding.UTF8.GetString(bytes, idx, bytes.Length - idx);
}
public static T DeserializeString<T>(String content)
{
using (TextReader reader = new StringReader(content))
{
XmlSerializer s = new XmlSerializer(typeof(T));
return (T)s.Deserialize(reader);
}
}
...
}