【问题标题】:xmlserializer not correctly deserializing schema with importxmlserializer 没有正确反序列化导入模式
【发布时间】:2010-01-27 20:36:07
【问题描述】:

我一直在尝试使用从 xsd.exe 中的模式生成的类来反序列化 C# 中的 xml 文件。不幸的是,只有部分文件被正确反序列化,其余部分由于我无法解决的原因返回为 null。

我的流程如下: 从生成 C# 代码的 myschema.xsd 文件开始:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mc="myschema:common" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ttl="http://www.myuri.org/myschema" targetNamespace="http://www.myuri.org/myschema" elementFormDefault="qualified" attributeFormDefault="unqualified">

而导入的parentschema.xsd文件是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:mc="myschema:common" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="myschema:common" elementFormDefault="qualified" attributeFormDefault="unqualified">
 <xs:element name="toplevel">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="mc:toplevel_header" minOccurs="0"/>
    <xs:element ref="mc:body"/>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 <xs:element name="toplevel_header">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="name" type="xs:anyURI"/>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 <xs:element name="body" type="mc:body" abstract="true"/>
 <xs:complexType name="body">
  <xs:attribute name="id" type="xs:ID" use="required"/>
 </xs:complexType>
 <xs:element name="Entity" type="mc:Entity" abstract="true"/>
 <xs:complexType name="Entity" abstract="true">
  <xs:attribute name="href" type="xs:anyURI" use="optional"/>
 </xs:complexType>
</xs:schema>

我将上述两个架构文件传递给 xsd.exe:

>xsd.exe /c myschema.xsd parentschema.xsd

生成一个 myschema_parentschema.cs 文件

为了测试它,我正在尝试反序列化一个示例 xml 文件:

<?xml version=\"1.0\" encoding="UTF-8"?>
<toplevel version="2.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xlink="http://www.w3.org/1999/xlink"
 xmlns="myschema:common"
 xsi:schemaLocation="myschema:common  http://www.myuri.org/parentschema.xsd">
 <toplevel_header>
     <name>MyName</name>
    </toplevel_header>
 <body id="body_1"
     xmlns="http://www.myuri.org/schema"
     xmlns:mc="myschema:common"
     xsi:schemaLocation="http://www.myuri.org/myschema http://www.myuri.org/myschema.xsd">
       <Foo href="http://www.google.com">
       </Foo>
    </body>
</toplevel>

我将其传递给以下 XmlSerializer 代码,其中 reader 是上述 xml 文件的 XmlReader:

XmlSerializer xs = new XmlSerializer ( typeof ( toplevel ) );
object deserializedObject = xs.Deserialize( reader );
toplevel fooBar = (toplevel)deserializedObject;
Assert.AreEqual( "MyName", fooBar.toplevel_header.name );  //passes OK
Assert.IsNotNull( fooBar.body ); //<--------FAIL

为什么反序列化的对象有一个 null body 属性,我如何让它正确反序列化 Foo 元素?

【问题讨论】:

标签: c# .net xsd xmlserializer


【解决方案1】:

您的 parentschema.xsd 中有一个错字。您正在为 body 标记提前关闭 &lt;xs:element&gt; 标记:

<xs:element name="body" type="mc:body" abstract="true"/>

您还将正文定义为抽象的,我认为这是一个错误(如果我正确阅读 XML)。

整个定义(基于您的 XML)应该类似于:

<xs:element name="body" type="mc:body" abstract="true">
    <xs:complexType>
        <xs:attribute name="id" type="xs:ID" use="required"/>
        <xs:sequence>
            <xs:element type="Foo" type="xs:anyURI" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

【讨论】:

    【解决方案2】:

    我按照与您相同的步骤进行操作,但您的架构和您要反序列化的 XML 文件似乎不匹配。这是我所做的:

    static void Main(string[] args)
    {
        var xs = new XmlSerializer(typeof(toplevel));
    
        // test saving to xml first...
        var tl = new toplevel();
        tl.toplevel_header = new toplevel_header();
        tl.toplevel_header.name = "MyName";
    
        tl.body = new body();
        tl.body.id = "body id...";
    
        // output to console first...
        var cw = Console.OpenStandardOutput();
        xs.Serialize(cw, tl);
        Console.WriteLine();
        Console.WriteLine();
    
        // save to file...
        var fw = File.CreateText("test.xml");
        xs.Serialize(fw, tl);
        fw.Close();
    
        // read file...
        var fr = File.Open("test.xml", FileMode.Open, FileAccess.Read);
        var obj = xs.Deserialize(fr);
        var fooBar = (toplevel)obj;
    
        Console.WriteLine(fooBar.toplevel_header.name);
        Console.WriteLine(fooBar.body.id);
        Console.ReadLine();
    }
    

    序列化程序生成的 XML 是这样的:

    <?xml version="1.0" encoding="utf-8"?>
    <toplevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns="myschema:common">
      <toplevel_header>
        <name>MyName</name>
      </toplevel_header>
      <body id="body id..." />
    </toplevel>
    

    XML 显然与您正在使用的输入 XML 文件不匹配...希望这对您有所帮助!

    【讨论】:

      【解决方案3】:

      查看您的示例 xml,我注意到不一致的地方,这就是 XmlSerializer 没有达到您期望的结果的原因:

      <toplevel version="2.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       ***xmlns="myschema:common"***
       xsi:schemaLocation="myschema:common  http://www.myuri.org/parentschema.xsd">
          <toplevel_header>
              <name>MyName</name>
          </toplevel_header>
          <body id="body_1"
                  ***xmlns="http://www.myuri.org/schema"***
                  ***xmlns:mc="myschema:common"***
                  xsi:schemaLocation="http://www.myuri.org/myschema http://www.myuri.org/myschema.xsd">
              <Foo href="http://www.google.com">
              </Foo>
          </body>
      </toplevel>
      

      在顶层元素中定义 xmlns="myschema:common",但在 body 元素中定义 xmlns="http://www.myuri.org/schema",下一行是 xmlns:mc =“myschema:常见”。这意味着正文中的 Foo 元素位于不同的命名空间下,XmlSerializer 将找不到该元素。当我删除 body 元素中的 xmlns 声明并将 xmlns:mc 声明更改为 xmlns 时,如下所示:

      <?xml version="1.0" encoding="UTF-8"?>
      <toplevel version="2.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       xmlns="myschema:common"
       xsi:schemaLocation="myschema:common  http://www.myuri.org/parentschema.xsd">
          <toplevel_header>
              <name>MyName</name>
          </toplevel_header>
          <body id="body_1"
                  xmlns="myschema:common"
                  xsi:schemaLocation="http://www.myuri.org/myschema http://www.myuri.org/myschema.xsd">
              <Foo href="http://www.google.com">
              </Foo>
          </body>
      </toplevel>
      

      按照指示调整示例 xml,XmlSerializer 创建了顶层对象,其中包含非空主体。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-21
        • 1970-01-01
        • 2019-04-06
        • 2012-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多