xmlserializer 未通过导入正确反序列化架构

发布于 2024-08-19 17:54:23 字数 3114 浏览 2 评论 0原文

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

我的流程如下: 从生成 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

Why does the deserialized object has a null body property, and how do I get it to deserialize Foo elementprops?

I've been trying to deserialize an xml file in C# with classes generated from schemas in xsd.exe. Unfortunately only part of the file is being properly deserialized, the rest is returned as null for reasons I can't work out.

My process is as follows:
Starting with the myschema.xsd file from which the C# code is generated:

<?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">

and the imported parentschema.xsd file is so:

<?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>

I'm passing the two above schema files to xsd.exe:

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

which generates a myschema_parentschema.cs file

To test it I'm trying to deserialize a sample xml file:

<?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>

which I'm passing to the following XmlSerializer code, where reader is an XmlReader for the above xml file:

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

Why does the deserialized object have a null body property, and how do I get it to deserialize the Foo element properly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烦人精 2024-08-26 17:54:23

您的parentschema.xsd 中有一个拼写错误。您过早地关闭了 body 标记的 标记:

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

您还将 body 定义为抽象,我认为这是一个错误(如果我正确读取 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>

There's a typo in your parentschema.xsd. You're closing the <xs:element> tag prematurely for the body tag:

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

You also define the body as abstract which I think is a mistake (if I'm reading the XML properly).

The whole definition (based on your XML) should look something like:

<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>
酒中人 2024-08-26 17:54:23

我按照与您相同的步骤操作,但您的架构和您要反序列化的 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 文件不匹配...希望这对您有所帮助!

I followed the same steps as you, and it looks like your schema and the XML file that you're deserializing are not matching. Here's what I did:

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

The XML that the serializer generated was this:

<?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>

The XML clearly does not match the input XML file you are using... Hopefully this helps you along your way!

娇俏 2024-08-26 17:54:23

查看您的示例 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:common"。这意味着主体内部的 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 创建了其中包含非空主体的顶级对象。

Looking at your sample xml I noticed a inconsistency which is the reason why the XmlSerializer is not coming up with what you expect:

<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>

In your toplevel element you are defining xmlns="myschema:common", and yet in your body element you are defining xmlns="http://www.myuri.org/schema" and the next line is xmlns:mc="myschema:common". This means that the Foo element inside of the body is under a different namespace and the XmlSerializer will not find the element. When I deleted the xmlns declaration in the body element and changed the xmlns:mc declaration to xmlns, like so:

<?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>

Having adjusted the sample xml as indicated the XmlSerializer created the toplevel object with a non-null body inside of it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文