代码之家  ›  专栏  ›  技术社区  ›  Jhonny D. Cano -Leftware-

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

  •  3
  • Jhonny D. Cano -Leftware-  · 技术社区  · 15 年前

    我有一个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,我发现要做的时间有点长…但如果没有别的选择,我会的。

    你认为最好的方法是什么?还有其他方法吗? 如果不是很长的话,我会把这个模式放在这里,如果它与这个问题相关的话。

    4 回复  |  直到 12 年前
        1
  •  6
  •   Cheeso    15 年前

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

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

    通常,我会调整序列化以省略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文档到内存中对象图的反向映射。使用反序列化方法。

        2
  •  2
  •   Andrew Siemer    15 年前

    我刚才写的一篇文章可能会引起你的兴趣。我不得不使用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编写器!

        3
  •  2
  •   Hans    12 年前

    这么好的推荐信…… http://msdn.microsoft.com/en-us/library/x6c1kb0s%28v=vs.110%29.aspx

    我刚刚为CSharp生成了带有字段的类:

    首先打开Visual Studio命令提示( 程序->VisualStudio->VisualStudioTools->VisualStudioCommandPrompt )

    然后更改为XSD文件的目录,然后运行以下命令:

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

    (将myxsdschemafile.xsd替换为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(Web上有大量示例)

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

        4
  •  0
  •   Josh Stodola    15 年前

    您可以创建XML,然后通过 Xml Schema Validator that I wrote .