问题序列化类XML和包括CDATA节 [英] Problems serializing a class to XML and including a CDATA section

查看:551
本文介绍了问题序列化类XML和包括CDATA节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个是通过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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆