Probleme mit der Serialisierung einer Klasse, um XML-und sogar mit einem CDATA-Abschnitt
Habe ich eine Klasse, die serialisiert in XML-für den Konsum durch einen web-service. In diesem Klassen-Instanz, die XML muss ein CDATA-Abschnitt für den web-service, es zu Lesen, aber ich bin ratlos, wie um dies zu implementieren.
Die XML muss so Aussehen:
<UpdateOrderStatus>
<Action>2</Action>
<Value>
<![CDATA[
<Shipment>
<Header>
<SellerID>
...
]]>
</Value>
</UpdateOrderStatus>
Ich bin in der Lage zu generieren, die entsprechende XML-Datei, mit Ausnahme der CDATA-Teil.
Meiner Klasse Struktur sieht wie folgt aus:
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();
}
....
Habe ich einige Anregungen mit:
[XmlElement("node", typeof(XmlCDataSection))]
aber, dass eine Ausnahme verursacht
Habe ich auch schon versucht
[XmlElement("Value" + "<![CDATA[")]
aber die resultierende XML ist falsch, zeigt
<Value_x003C__x0021__x005B_CDATA_x005B_>
....
</Value_x003C__x0021__x005B_CDATA_x005B_>
Kann jemand mir zeigen, was ich falsch mache, oder wo ich mit diesem zu gehen?
--Edit--
machen shipmentInfo serializable pro carlosfigueira funktioniert für die meisten Teil, aber ich habe das extra ? Zeichen in der resultierenden XML ( siehe post Schreiben Sie ein XML-fragment mit XmlWriterSettings und XmlSerializer gibt einen extra Charakter für details )
Als solche änderte ich das Schreiben von XML-Code-Methode:
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()));
}
}
}
Aber ich bin nicht immer eine Ausnahme:
System.InvalidOperationException: There was an error generating the XML document. ---> System.ArgumentException: '.', hexadecimal
value 0x00, is an invalid character.
--Edit --
Ausnahme wurde durch die Einbeziehung von meiner vorherigen serializeToString Methode. Da das entfernen, dass die CDATA-Ausgabe ist korrekt, außer für ein spacing Problem, aber ich bin auch immer ein namespace und xml-Deklaration sollte entfernt werden, indem die XML-Einstellungen angegeben. Ausgabe:
<?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>
Irgendwelche Ideen, um die BOM mit der neuen Klasse?
Bearbeiten--3 -- ERFOLG!
Habe ich umgesetzt vorgeschlagenen änderungen unten, und jetzt haben Sie die folgenden writer-Klassen und test-Methoden:
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());
}
}
Führt dies zu den folgenden XML-Code:
<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>
InformationsquelleAutor Robert H | 2012-07-13
Du musst angemeldet sein, um einen Kommentar abzugeben.
In Reaktion auf die "Räume" Sie werden sehen, nach deinem edit ist es aufgrund der Kodierung (Unicode, 2 Byte pro Zeichen).
Versuchen:
EDIT:
Beachten Sie auch, dass das format der
MemoryStream
ist nicht unbedingt eine gültige UTF-8-codierte Zeichenfolge! Sie können eineStringBuilder
stattMemoryStream
zu erstellen Sie Ihre innere Schriftsteller.Ich denke, das ist, weil die
MemoryStream
Inhalte sind nicht notwendigerweise eine gültige UTF-8-codierte Zeichenfolge. Ich aktualisiert meine Antwort.InformationsquelleAutor Monroe Thomas
Könnte dies helfen: http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.createcdatasection.aspx
Auch, welche Ausnahme Sie bekommen, wenn Sie das Attribut?
-- edit --
Könnten Sie versuchen, hinzufügen einer benutzerdefinierten Klasse, und tun Sie etwas wie dieses:
Als hier gefunden http://bytes.com/topic/net/answers/530724-cdata-xmltextattribute
Versuchen Sie das Attribut wie in diesem [XmlElement("CDataElement")]
wenn ich das Tue, es benennt Wert CDataElement, die nicht die web-service-Validierung
Ich habe auch versucht: UpdateString.Replace(@"<Wert>", @"<Value><![CDATA["); UpdateString.Replace(@"</Value>", @"]]></Value>"); mit kein Glück
Siehe Bearbeiten 🙂 Fügen Sie Ihre eigenen CDATA-Typ und verwenden Sie das Attribut wie im obigen Klasse in eine eigene Klasse
InformationsquelleAutor Gerald Versluis
Umsetzung ShipmentInfo als
IXmlSerializable
- Typ wird in der Nähe erhalten, was Sie brauchen - siehe Beispiel unten.Um das BOM entfernen, legen Sie die
Encoding
Eigenschaft des XmlWriterSettings, die ohne eine Instanz der Stückliste:new XmlWriterSettings { OmitXmlDeclaration = true, Encoding = new UTF8Encoding(false) }
InformationsquelleAutor carlosfigueira
Beispiel unten ist nur, wenn die Struktur des Schemas definiert ist und Sie keine andere Wahl haben der änderung des Schemas.
Beim Deserialisieren/Serialisieren [xmltext] Wert, ist es sehr schwer zu halten den text in CDATA[]
umschließen. Sie können compiletransform, um die CDATA-Wert in der xml wie es ist, aber das CDATA ist verloren, sobald Sie Deserialisieren in C# und Last memory-Zeug.
Dies ist einer der einfachste Weg, dies zu tun
1) Deserialisieren/Serialisieren
2) sobald die endgültige xml-output abgeleitet.
Die fertige xml-Datei kann
werden in eine Zeichenfolge konvertiert und analysiert, wie unten dargestellt aus und schicken Sie es als string einbetten CDATA dem test1 Wert.
string xml ="@#@!#!#!@#!@#%$%@#$%#$%";
XNamespace-ns = @"";
XDocument doc = XDocument.Parse(xml);
string xmlString = string.Leer;
var coll = aus Abfrage in doc.Nachkommen(ns + "test1")
select-Abfrage;
foreach (var-Wert in coll){
Wert.ReplaceNodes(neue XCData(Wert .Wert));}
doc.speichern("test.xml");//umwandeln in doc.tostring()
InformationsquelleAutor user3255162
Ich denke carlosfigueira gab nur eine elegante Antwort, aber vielleicht ein wenig schwer zu verstehen, auf den ersten Blick. Hier ist eine alternative für Ihre Aufmerksamkeit, können Sie Serialisieren/Deserialisieren
UpdateOrderStatus
undShipmentInfo
getrennt.Definieren business-Objekt-Klasse:
Beachten Sie, dass Sie verwenden sollten
XmlCDataSection
für dieValue
Feld.Hier ist der test - /Hilfsfunktionen:
InformationsquelleAutor Jiaji Wu