XSD类生成嵌套表问题

时间:2008-12-29 10:07:18

标签: c# xml .net-2.0 xsd

目前我遇到了从带有重复元素的xsd生成类文件的问题。我在VS2005 SP1中使用自定义工具'MsDatasetGenerator',从xsd为c#创建一个类型化数据集。我正在尝试通过此架构解析xml

    <?xml version="1.0" encoding=\"utf-8\"?>
<xs:schema id="XSDobject" targetNamespace="http://tempuri.org/XSDobject.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XSDobject.xsd" xmlns:mstns="http://tempuri.org/XSDobject.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="order">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="contact">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="name" type="xs:string" />
                            <xs:element name="phone" type="xs:string" />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="buyer">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="contact">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="name" type="xs:string" />
                                        <xs:element name="phone" type="xs:string" />
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

但我得到以下错误“同一个表'联系人'不能是两个嵌套关系中的子表。

XSD正确编译,但它是无法处理重复表的类型化数据集。现在我也测试了xsd.exe工具,但它似乎生成与msdatasetgenerator相同的代码。我还尝试了一些第三方代码生成器工具,如XSD2Code,CodeXS,AltovaXmlSpy,但我也无法使用嵌套元素。

或者我可以在输入和输出处解决xslt转换的问题但是它会花费我很多性能。

所以现在我问是否有人可以帮助我为VS2005提供一个好的解决方案,或者知道可以解决这个问题的好的xsd类生成器。它不必是类型化的数据集,如果它作为数组或列表工作,它也是完美的,只要它很容易序列化和反序列化。

提前致谢 Freggel

4 个答案:

答案 0 :(得分:2)

我有同样的问题..如果性能不是问题,你可以使用XSLT重命名具有相同名称的“子”表(即结果名称是表名与其父级的串联):

 ...
  <xsl:template match="*">
     <xsl:param name="parentElm">
       <xsl:value-of select="name(..)" />
     </xsl:param>
     <xsl:choose>
       <xsl:when test="local-name() = 'Contact'">
         <xsl:element name="{concat('Contact',$parentElm)}">
           <xsl:apply-templates select="@* | node()" />
         </xsl:element>
       </xsl:when> <xsl:otherwise>
         <xsl:element name="{local-name()}">
           <xsl:copy-of select="@*" />
           <xsl:apply-templates select="@* | node()" />
         </xsl:element>
       </xsl:otherwise>
     </xsl:choose>   </xsl:template> ...

答案 1 :(得分:1)

我建议简单地重命名模式项,加上分组的使用(如下所示)或xsd包含(如果你需要这种复杂类型用于其他模式)。如果您对名称没有严格的要求,这应该可以解决问题。

根据经验,我认为工具不会与您的示例中的重复命名一起使用。

这样的事情可以解决问题:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="XSDobject" targetNamespace="http://tempuri.org/XSDobject.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XSDobject.xsd" xmlns:mstns="http://tempuri.org/XSDobject.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:group name="Contact">
    <xs:sequence>
      <xs:element name="name" type="xs:string" />
      <xs:element name="phone" type="xs:string" />
    </xs:sequence>
  </xs:group>
  <xs:element name="order">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="OrderContact">
          <xs:complexType>
            <xs:sequence>
              <xs:group ref="Contact"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="buyer">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="BuyerContact">
                <xs:complexType>
                  <xs:sequence>
                    <xs:group ref="Contact"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

答案 2 :(得分:0)

也许您可以使用xsd:import / xsd:include将xsd拆分为多个文件,然后使用xsd.exe编译每个文件。我认为您可以指定命名空间以生成使用xsd.exe时的代码。

我在几年前从xsd:s生成类,并且由于某种原因我决定使用xsdobjgen.exe而不是xsd.exe。

祝你好运!

答案 3 :(得分:0)

查看我的解决方案。

The same table 'name' cannot be the child table in two nested relations

我建议在架构中使用'ref'来引用'重复'元素。