2009-06-01 8 views
20

Je suis en train de générer XML comme ceci:XML .NET sérialisation sans déclaration <?xml> texte

<?xml version="1.0"?> 
<!DOCTYPE APIRequest SYSTEM 
"https://url"> 
<APIRequest> 
    <Head> 
     <Key>123</Key> 
    </Head> 
    <ObjectClass> 
    <Field>Value</Field 
    </ObjectClass> 
</APIRequest> 

J'ai décoré avec XmlSerialization attributs comme cette classe (ObjectClass):

[XmlRoot("ObjectClass")] 
public class ObjectClass 
{ 
    [XmlElement("Field")] 
    public string Field { get; set; } 
} 

Et ma pensée intuitive vraiment hacky juste pour obtenir ce travail est de le faire quand je sérialiser:

ObjectClass inst = new ObjectClass(); 
XmlSerializer serializer = new XmlSerializer(inst.GetType(), ""); 

StringWriter w = new StringWriter(); 
w.WriteLine(@"<?xml version=""1.0""?>"); 
w.WriteLine("<!DOCTYPE APIRequest SYSTEM"); 
w.WriteLine(@"""https://url"">"); 
w.WriteLine("<APIRequest>"); 
w.WriteLine("<Head>"); 
w.WriteLine(@"<Field>Value</Field>"); 
w.WriteLine(@"</Head>"); 

XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
ns.Add("", ""); 
serializer.Serialize(w, inst, ns); 

w.WriteLine("</APIRequest>"); 

Cependant, cela génère XML comme ceci:

<?xml version="1.0"?> 
<!DOCTYPE APIRequest SYSTEM 
"https://url"> 
<APIRequest> 
    <Head> 
     <Key>123</Key> 
    </Head> 
    <?xml version="1.0" encoding="utf-16"?> 
    <ObjectClass> 
    <Field>Value</Field> 
    </ObjectClass> 
</APIRequest> 

à savoir la déclaration de serialize ajoute automatiquement une déclaration de texte <? Xml.

Je sais que j'attaque ce problème alors quelqu'un peut-il me diriger dans la bonne direction? En guise de note, je ne pense pas qu'il soit judicieux de créer une classe APIRequest avec une classe ObjectClass (parce qu'il y a 20 types différents d'ObjectClass qui ont besoin de cette classe), mais corrigez-moi si j'ai tort.

+0

Automatiquement? Vous semblez ajouter la déclaration manuellement: w.WriteLine (@ "") ;. – Cerebrus

+1

@Cerebrus, il ne veut pas l'intérieur à l'intérieur de la balise . – sisve

+0

Ouais c'est ça merci pour avoir éclairci ça :-) –

Répondre

24

Ne construisez jamais de xml en utilisant une concaténation de chaîne. C'est diabolique.

Sortie:

<?xml version="1.0" encoding="utf-16"?> 
<!DOCTYPE APIRequest SYSTEM "https://url"> 
<APIRequest> 
    <Head> 
    <Key>123</Key> 
    </Head> 
    <ObjectClass> 
    <Field>Value</Field> 
    </ObjectClass> 
</APIRequest> 

code:

using System; 
using System.Diagnostics; 
using System.Text; 
using System.Xml; 
using System.Xml.Serialization; 

public static class Program { 
    public static void Main() { 
     var obj = new ObjectClass { Field = "Value" }; 

     var settings = new XmlWriterSettings { 
      Indent = true 
     }; 

     var xml = new StringBuilder(); 
     using (var writer = XmlWriter.Create(xml, settings)) { 
      Debug.Assert(writer != null); 

      writer.WriteDocType("APIRequest", null, "https://url", null); 
      writer.WriteStartElement("APIRequest"); 
      writer.WriteStartElement("Head"); 
      writer.WriteElementString("Key", "123"); 
      writer.WriteEndElement(); // </Head> 

      var nsSerializer = new XmlSerializerNamespaces(); 
      nsSerializer.Add("", ""); 

      var xmlSerializer = new XmlSerializer(obj.GetType(), ""); 
      xmlSerializer.Serialize(writer, obj, nsSerializer); 

      writer.WriteEndElement(); // </APIRequest> 
     } 

     Console.WriteLine(xml.ToString()); 
     Console.ReadLine(); 
    } 
} 

[XmlRoot("ObjectClass")] 
public class ObjectClass { 
    [XmlElement("Field")] 
    public string Field { get; set; } 
} 
+0

Merci, je savais que la concaténation des cordes était mauvaise mais je pensais que ça marcherait au moins - je suppose que non! Merci :-) –

+0

Juste vérifié - merci tas! –

+0

Je ne dirais pas que c'est mal. Ce n'est pas ce que vous préférez, mais si vous avez des situations dans lesquelles la performance est cruciale et que vous avez identifié l'auteur comme la source de cette performance, l'utilisation de la concaténation de chaînes peut être un gain énorme. Bien sûr, il est situationnel, et j'utiliserais presque toujours XmlWriter, mais dans certains cas, il est justifié. – casperOne

1

Derive votre propre XmlTextWriter d'omettre la déclaration XML.

Private Class MyXmlTextWriter 
Inherits XmlTextWriter 
Sub New(ByVal sb As StringBuilder) 
    MyBase.New(New StringWriter(sb)) 
End Sub 
Sub New(ByVal w As TextWriter) 
    MyBase.New(w) 
End Sub 

Public Overrides Sub WriteStartDocument() 
    ' Don't emit XML declaration 
End Sub 
Public Overrides Sub WriteStartDocument(ByVal standalone As Boolean) 
    ' Don't emit XML declaration 
End Sub 
End Class 

Appelez Serialize avec une instance du dérivé MyXmlTextWriter.

Dim tw As New MyXmlTextWriter(sb) 
Dim objXmlSerializer As New XmlSerializer(type) 
objXmlSerializer.Serialize(tw, obj) 
+2

@Doug D: J'ai du mal à croire que vous considérez cela comme une meilleure solution. –

1

Scott Hanselman's a reçu un bon post à ce sujet. J'ai utilisé l'exemple de Kzu (que signale le blog de Scott) il y a quelque temps pour la même chose et ça a très bien fonctionné.

+2

@Tone: une sorte de meee-tooo? C'est exactement ce que Doug D a dit il y a un mois. -1. –

-2

Un liner, pour enlever la première ligne d'une chaîne:

String.Join("\n", strXML.Split('\n').Skip(1).ToArray()) 

Pas élégant, mais concis.

+1

-1: comment ça aide? –

30

essayez ceci:

internal static string ToXml(object obj) 
{ 
    string retval = null; 
    if (obj != null) 
    { 
    StringBuilder sb = new StringBuilder(); 
    using(XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { OmitXmlDeclaration = true })) 
    { 
     new XmlSerializer(obj.GetType()).Serialize(writer, obj); 
    } 
    retval = sb.ToString(); 
    } 
    return retval; 
} 
2

Si vous ne voulez pas compter sur un écrivain xml pour des raisons de performances, etc vous pouvez le faire.

// Read into memory stream and set namespaces to empty strings 
XmlSerializerNamespaces nsSerializer = new XmlSerializerNamespaces(); 
nsSerializer.Add(string.Empty, string.Empty); 
XmlSerializer xs = new XmlSerializer(typeof(Model.AudioItem)); 
xs.Serialize(ms, item, nsSerializer); 

// Read into UTF-8 stream and read off first line (i.e "<?xml version="1.0"?>") 
StreamReader sr = new StreamReader(ms); 
ms.Position = 0; 
sr.ReadLine(); 

sr.ReadToEnd() ToString () contient maintenant la sérialisation nue

+0

se sent sale, et pourtant intelligent, pour le tour ReadLine. J'aime ça. Des soucis avec indentation et tel? – sirthomas

-1
if (!string.IsNullOrEmpty(strXML) && strXML.Contains(@"<?xml")) 
strXML = strXML.Remove(0, strXML.IndexOf(@"?>", 0) + 2); 
+0

strXML = strXML.Remove (0, sXMLContent.IndexOf (@ "?>", 0) + 2); – sas

+1

pouvez-vous s'il vous plaît expliquer votre réponse? – CoderPi

Questions connexes