创建符合XSD架构的XML文档的最佳方法是什么?

时间:2009-06-18 20:36:02

标签: c# xml xml-serialization xsd

我有一个XSD,我必须生成一个XML文档发送给我合作的公司的客户。我发送的文档将根据此XSD架构进行验证。

创建符合XSD架构的XML文档的最佳方法是什么?我的意思是,我正在寻找最佳实践等。我是新手,在这里和那里“谷歌搜索”时,我发现人们使用XmlTextWriter,DataSet.WriteXml和其他人。

  1. DataSet.WriteXml似乎不适合我。这就是我所做的:

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

    我发现它使用NewDataSet生成一个节点,并且节点的顺序不正确。

  2. XmlTextWriter,我发现它有点长...但如果没有别的选择,我会的。

  3. 您认为最好的方法是什么?还有其他办法吗? 如果时间不长,我会把模式放在这里,如果它与问题相关。

4 个答案:

答案 0 :(得分:6)

.NET中的主流实践是使用XML Serialization

在你的情况下,我会这样做:

  • 在.XSD上运行xsd.exe以生成类的源代码(xsd / c)
  • 构建利用这些生成的类的应用程序。请记住,您可以通过“部分类”技术扩展这些类
  • 在代码中,实例化XmlSerializer,并序列化类实例。

示例:

鉴于此架构:

<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生成此源代码:

[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;
        }
    }
}

在你的应用程序中,你可以实例化一个Foo然后序列化,如下所示:

    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();

此示例序列化为字符串。当然,您可以序列化到其他XmlWriters,您可以写出文件,任意流,等等。

通常我会调整序列化以省略XML声明,省略默认的xml命名空间,依此类推。像这样:

    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();

您还可以使用XmlSerializer进行反向映射,从XML文档映射到内存中对象图。使用Deserialize方法。

答案 1 :(得分:2)

我刚才写的帖子可能会引起您的兴趣。我不得不使用BizTalk,发现从XSD生成我的类,然后通过线路(wa-la XML)序列化该类工作得很好!

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

这使您可以将数据作为一个类以及与之一起使用的所有特权。它完全允许您绕过XML编写器!

答案 2 :(得分:2)

这么棒的参考.. http://msdn.microsoft.com/en-us/library/x6c1kb0s%28v=vs.110%29.aspx

我刚刚使用csharp的字段生成了类:

首先打开visual studio命令提示符(程序 - &gt; visualStudio-&gt; visualstudioTools-&gt; VisualstudioCommandPrompt

然后切换到xsd文件的目录,然后运行以下命令:

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

(用您的xsd文件名替换MyXSDSCHEMAFILE.xsd)

创建cs文件后,将其复制到所有其他cs文件所在的项目文件夹中,并通过右键单击项目并添加现有项目将其添加到visual studio中的项目中。完成后,转到您要使用类的代码段,并像这样初始化(classname是在cs文件中创建的类):

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

然后序列化为xml(网上的大量例子)

有用的提示: 请注意,实例化并不总是xsd创建的类的一部分 确保正确创建对象以避免空指针异常。

答案 3 :(得分:0)

您可以创建XML,然后通过Xml Schema Validator that I wrote运行它。