2009-06-18 6 views
3

Ich habe eine XSD und ich muss ein XML-Dokument generieren, um es an die Kunden der Firma zu senden, mit der ich arbeite. Die Dokumente, die ich sende, werden anhand dieses XSD-Schemas überprüft.Was ist der beste Weg, um ein XML-Dokument zu erstellen, das einem XSD-Schema entspricht?

Was ist der beste Weg, um ein XML-Dokument zu erstellen, das einem XSD-Schema entspricht? Ich meine, ich suche nach Best Practices und ähnlichem. Ich bin neu dazu und während ich hier und da "googelt", habe ich Leute gefunden, die XmlTextWriter, DataSet.WriteXml und andere benutzen.

  1. DataSet.WriteXml scheint für mich nicht gut zu funktionieren. Das ist, was ich tat:

    var ds = new DataSet(); 
    ds.ReadXmlSchema(schemaFile); 
    ds.Tables["TableName"].Rows.Add("", "", 78, true, DateTime.Now); 
    ... 
    ds.WriteXml("C:\\xml.xml"); 
    

    Ich fand es erzeugt einen Knoten mit NewDataSet, und die Knoten sind nicht in der richtigen Reihenfolge.

  2. XmlTextWriter, ich finde es ein bisschen lang zu tun ... aber ich werde, wenn es keine andere Wahl gibt.

Was denken Sie, ist der beste Weg, dies zu tun? Gibt es andere Ansätze, dies zu tun? Ich würde das Schema hier setzen, wenn es nicht so lange wäre, und wenn es für die Frage relevant wäre.

Antwort

6

Die gängige Praxis in. NET ist XML Serialization zu verwenden.

In Ihrem Fall würde ich dies tun:

  • laufen die xsd.exe auch auf .XSD auf den Quellcode für die Klassen (xsd/c)
  • bauen Sie Ihre App zu generieren, die diese generierten Klassen verwendet . Beachten Sie, dass Sie diese Klassen über die Methode "partial classes"
  • in Code erweitern, einen XmlSerializer instanziieren und die Klasseninstanzen serialisieren können.

Beispiel:

Vor diesem Schema:

<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="Foo" nillable="true" type="Foo" /> 
    <xs:complexType name="Foo"> 
    <xs:sequence> 
     <xs:element minOccurs="0" maxOccurs="1" name="Bar" type="xs:string" /> 
     <xs:element minOccurs="0" maxOccurs="1" name="Baz" type="UntypedArray" /> 
    </xs:sequence> 
    </xs:complexType> 


    <xs:complexType name="UntypedArray"> 
    <xs:choice minOccurs="1" maxOccurs="unbounded"> 
     <xs:element name="Type1" type="Type1"     minOccurs="1" maxOccurs="1"/> 
     <xs:any  namespace="##other" processContents="lax" minOccurs="1" maxOccurs="1"/> 
    </xs:choice> 
    </xs:complexType> 


    <xs:complexType name="Type1" mixed="true"> 
    <xs:sequence> 
     <xs:element minOccurs="0" maxOccurs="1" name="Child" type="xs:string" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

xsd.exe erzeugt diesen Quellcode:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=true)] 
public partial class Foo { 

    private string barField; 

    private object[] bazField; 

    /// <remarks/> 
    public string Bar { 
     get { 
      return this.barField; 
     } 
     set { 
      this.barField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlArrayItemAttribute("", typeof(System.Xml.XmlElement), IsNullable=false)] 
    [System.Xml.Serialization.XmlArrayItemAttribute(typeof(Type1), IsNullable=false)] 
    public object[] Baz { 
     get { 
      return this.bazField; 
     } 
     set { 
      this.bazField = value; 
     } 
    } 
} 

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
public partial class Type1 { 

    private string childField; 

    private string[] textField; 

    /// <remarks/> 
    public string Child { 
     get { 
      return this.childField; 
     } 
     set { 
      this.childField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlTextAttribute()] 
    public string[] Text { 
     get { 
      return this.textField; 
     } 
     set { 
      this.textField = value; 
     } 
    } 
} 

In Ihrer App Sie Foo instanziiert und dann serialisiert, so:

Foo foo = new Foo(); 
    // ...populate foo here... 
    var builder = new System.Text.StringBuilder(); 
    XmlSerializer s = new XmlSerializer(typeof(Foo)); 
    using (var writer = System.Xml.XmlWriter.Create(builder)) 
    { 
     s.Serialize(writer, foo, ns); 
    } 
    string rawXml = builder.ToString(); 

Dieses Beispiel wird in eine Zeichenfolge serialisiert.Natürlich können Sie mit anderen XmlWritern serialisieren, Sie können in eine Datei schreiben, in irgendeinen beliebigen Stream und so weiter.

Normalerweise zwicke ich die Serialisierung, um die XML-Deklaration wegzulassen, die Standard-XML-Namespaces wegzulassen und so weiter. Wie folgt aus:

Foo foo = new Foo(); 
    // ...populate foo here... 
    var builder = new System.Text.StringBuilder(); 
    var settings = new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent= true }; 
    var ns = new XmlSerializerNamespaces(); 
    ns.Add("",""); 
    XmlSerializer s = new XmlSerializer(typeof(Foo)); 
    using (var writer = System.Xml.XmlWriter.Create(builder, settings)) 
    { 
     s.Serialize(writer, foo, ns); 
    } 
    string rawXml = builder.ToString(); 

Sie auch die umgekehrten tun kann - Karte aus einem XML-Dokument an einen In-Memory-Objektgraph - die XmlSerializer verwenden. Verwenden Sie die Deserialize-Methode.

+0

Txs, ich denke, es hat gut funktioniert, aber ich werde es testen ... eine andere Frage, wie kann ich die XML-Ausgabe "verschönern"? ich meine ... ich möchte auch eine menschlichere lesbare xml haben ... –

+0

hängt davon ab, was Sie mit "verschönern" meinen. Wenn Sie "Einrückung" meinen, dann sorgt der zweite Code-Ausschnitt oben für eine eingerückte XML-Ausgabe. Wenn Sie etwas anderes meinen, erklären Sie bitte. – Cheeso

+0

Ja, ich meinte Indent, danke ... ich habe es schon gelesen !! –

2

Ein Beitrag, den ich vor einiger Zeit geschrieben habe, könnte Sie interessieren. Ich musste mit BizTalk arbeiten und fand heraus, dass das Generieren meiner Klassen von einer XSD und das anschließende Serialisieren dieser Klasse über die Leitung (wa-la XML) ziemlich gut funktionierte!

http://blog.andrewsiemer.com/archive/2008/04/30/accepting-xmldocuments-from-biztalk-de-serializing-them-to-xsd-generated-serializable.aspx

Auf diese Weise können Sie mit den Daten als eine Klasse arbeiten und alle Vergünstigungen, die mit, dass entlang gehen. Und es erlaubt Ihnen völlig die XML-Writer zu umgehen!

2

Solch große Referenz .. http://msdn.microsoft.com/en-us/library/x6c1kb0s%28v=vs.110%29.aspx

ich gerade generierten Klassen mit Feldern für csharp:

Zuerst Visual Studio-Eingabeaufforderung öffnen (programs-> visualStudio-> visualstudioTools-> VisualstudioCommandPrompt)

dann sind Sie in das Verzeichnis Ihrer XSD-Datei ändern und dann den folgenden Befehl ausführen:

xsd /classes /fields /language:CS MyXSDSCHEMAFILE.xsd 

(ersetzen Sie die MyXSDSCHEMAFILE.xsd mit Ihrem XSD Dateiname)

nach dem cs-Datei erstellt wird, kopieren Sie sie in Ihrem Projektordner, wo alle anderen cs-Datei und fügen Sie es dem Projekt in Visual Studio durch Klicken Sie mit der rechten Maustaste auf das Projekt und fügen Sie das vorhandene Objekt hinzu. Sobald das ist unterwegs, um Ihren Code-Segment abgeschlossen, wo Sie Ihre Klasse verwenden möchten, und wie diese initialisieren (classname ist die Klasse, in der cs-Datei erstellt wurde):

classname myvariablename = new classname(); // so easy :) 
// now you just fill with content 
myvariablename.whatever.andever.field = "JaWerHatDasErfunden";// you just set a field 

dann als XML (Tonnen Beispiele Serialisierung auf die Web)

Nützlicher Hinweis: Beachten Sie, dass Instanziierung nicht immer Teil der xsd erstellt Klassen ist.
Stellen Sie sicher, dass Sie Ihre Objekte ordnungsgemäß erstellen, um Nullzeiger-Ausnahmen zu vermeiden.

Verwandte Themen