反序列化经过验证的 XML 时出现问题,无法与数组相互转换

发布于 2024-07-18 04:56:58 字数 1197 浏览 2 评论 0原文

我有点不适应。 我使用 xsd.exe 从 xml 文件创建 xsd 架构,然后从该 xsd 创建 C# 类。 这一切似乎都运作良好。

目前我只是想反序列化 XML。 我正在反序列化的文件是否与我最初用来构建该类的文件完全相同。 这是我的代码:

String xsdPath=@"C:\Users\tol56881\Documents\dnd4e.xsd";
String xmlPath=@"C:\Users\tol56881\Documents\dnd4e.xml";
String xsdNamespace="";

//Validation stuff
XmlParserContext context = new XmlParserContext(null, null, "", XmlSpace.None);
XmlValidatingReader vr = new XmlValidatingReader(xmlPath, XmlNodeType.Element, context);
vr.ValidationType = ValidationType.Schema;
vr.Schemas.Add(xsdNamespace, xsdPath);
while (vr.Read()) ;

//Actually reading the file
TextReader tr = new StreamReader(xmlPath);
D20Character character = (D20Character)(new XmlSerializer(typeof(D20Character))).Deserialize(tr);

它编译得很好,但是当我尝试运行它时,我收到一个针对四个不同对象重复出现的错误。 我在下面给出了一个示例,更改对象的名称。

Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'Namespace.ObjectName[]' to 'Namespace.ObjectName'
error CS0029: Cannot implicitly convert type 'Namespace.ObjectName' to 'Namespace.ObjectName[]'

所以看起来程序正在尝试从数组到对象再返回数组,但我不太确定。 自动生成的类代码非常混乱,很难浏览。 我希望也许我在这里缺少一些简单的东西。

谢谢!

I'm a bit out of my element. I've used xsd.exe to create an xsd schema from an xml file, and then to create a C# class from that xsd. That all seems to work fine.

At the moment I'm just trying to get the XML deserialized. The file I'm deserializing if the very same file I used to build the class originally. Here's my code:

String xsdPath=@"C:\Users\tol56881\Documents\dnd4e.xsd";
String xmlPath=@"C:\Users\tol56881\Documents\dnd4e.xml";
String xsdNamespace="";

//Validation stuff
XmlParserContext context = new XmlParserContext(null, null, "", XmlSpace.None);
XmlValidatingReader vr = new XmlValidatingReader(xmlPath, XmlNodeType.Element, context);
vr.ValidationType = ValidationType.Schema;
vr.Schemas.Add(xsdNamespace, xsdPath);
while (vr.Read()) ;

//Actually reading the file
TextReader tr = new StreamReader(xmlPath);
D20Character character = (D20Character)(new XmlSerializer(typeof(D20Character))).Deserialize(tr);

It compile fine, but when I try to run it I get the an error that's repeated for four different objects. I've given an example below, changing the names of the objects.

Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'Namespace.ObjectName[]' to 'Namespace.ObjectName'
error CS0029: Cannot implicitly convert type 'Namespace.ObjectName' to 'Namespace.ObjectName[]'

So it seems like the program is trying to go from array to object and back to array, but I'm not really sure. The auto-generated class code is a huge mess that's difficult to wade through. I'm hoping that maybe there's something simple I'm missing here.

Thanks!

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

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

发布评论

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

评论(2

瞳孔里扚悲伤 2024-07-25 04:56:58

我设法解决了这个问题。 有问题的四个对象中的每一个都是作为双索引数组生成的,例如:

    private loot[][] lootTallyField;

并且

    public loot[][] LootTally
    {
        get
        {
            return this.lootTallyField;
        }
        set
        {
            this.lootTallyField = value;
        }
    }

我所做的就是删除一组括号,并且一切似乎都工作正常。 反序列化没有问题,并且快速检查反序列化对象使得数据看起来像是正确加载的。

    private loot[] lootTallyField;

并且

    public loot[] LootTally
    {
        get
        {
            return this.lootTallyField;
        }
        set
        {
            this.lootTallyField = value;
        }
    }

仍然不确定为什么 xsd.exe 使这些不应该是双索引的。 我觉得我仍然缺少一些东西,因此为什么这个问题仍然悬而未决。

特别是,如果我需要重新生成此代码,那么我需要重新应用修复程序,这首先就违背了使用部分类的目的......

I managed to fix this. Each of the four objects in question were generated as doubly-indexed arrays, such as:

    private loot[][] lootTallyField;

and

    public loot[][] LootTally
    {
        get
        {
            return this.lootTallyField;
        }
        set
        {
            this.lootTallyField = value;
        }
    }

All I did was remove one set of brackets, and it all seems to be working fine. No problems with deserialization and a quick inspection of the deserialized object makes it look like the data was loaded correctly.

    private loot[] lootTallyField;

and

    public loot[] LootTally
    {
        get
        {
            return this.lootTallyField;
        }
        set
        {
            this.lootTallyField = value;
        }
    }

Still not sure why xsd.exe made these doubly-indexed if they're not supposed to be. I feel like I'm still missing something, hence why this question is still open.

Particularly, if I ever need to re-generate this code, then I'd need to reapply the fix, which kind of defeats the purpose of using a partial class in the first place...

你是年少的欢喜 2024-07-25 04:56:58

xsd.exe 工具有问题,我会尽力解释。

如果您有一个内部带有序列的复杂类型,其中有一个带有序列的子复杂类型,并且第一个没有任何其他元素/属性,那么生成的类将只有 1 个生成类型,而不是 2 个,并且它将是一个双精度类型大批。

如果将双数组变成单个数组,则可以很好地反序列化 xml。
然而,这会产生以下意想不到的结果。
如果您的 xml 如下所示。

<root>
    <loot>
        <tally>value1</tally>
        <tally>value2</tally>
    </loot>
    <loot>
        <tally>value3</tally>
        <tally>value4</tally>
    </loot>
</root>

然后,您的反序列化对象在 lootTally 数组中将仅包含 value3 和 value4 项,而不是全部 4 个项。

因此,您有 2 个选项可以正确修复此问题:

  1. 通过在第一个序列中添加虚拟值来更改 xsd 文件,然后运行 ​​xsd。再次运行exe,这样生成类时就不会创建double数组,然后就可以从类中删除dummy属性了。
  2. 更改生成的类,添加一个名为 loot 的新类,它将包含您已经拥有的计数对象数组(并且只需要更改名称)。

请注意,在选项 2 中,如果您将 XmlArrayItemAttribute 更改为 XmlElementAttribute,则可能需要更改一些声明。

希望这可以帮助

There is a problem on xsd.exe tool, I will try to explain.

If you have a complexType with a sequence inside that has a child complexType with a sequence and the first one does not have any other elements / attributes, then the generated class will have only 1 generated type, instead of 2 and it will be a double array.

If you make the double array into a single array, you will be able to deserialize your xml just fine.
HOWEVER this will produce the following unexpected result.
If your xml looks like the below.

<root>
    <loot>
        <tally>value1</tally>
        <tally>value2</tally>
    </loot>
    <loot>
        <tally>value3</tally>
        <tally>value4</tally>
    </loot>
</root>

Then your deserialized object, in the lootTally array would only contain the value3 and value4 items instead of having all 4.

So you have 2 options to fix this correctly:

  1. Alter the xsd file by adding a dummy in the first sequence, and run xsd.exe again, so that when it generates the class it will not create a double array, and then you can delete the dummy attribute from the class.
  2. Alter the generated class, add a new class named loot which will contain an array of tally objects which you already have (and only need to alter the name).

Please note that in option 2 you may have to change some declarations if you have an XmlArrayItemAttribute to XmlElementAttribute.

Hope this helps

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