【问题标题】:C# XmlSerializer ignores xs:attribute with types other than xs:stringC# XmlSerializer 忽略 xs:attribute 类型不是 xs:string
【发布时间】:2011-02-09 13:35:01
【问题描述】:

我的问题似乎很奇怪,我没有发现任何其他问题,所以我想这是一个非常简单和愚蠢的错误,我似乎无法找出。

我有一个 XSD,我使用 xsd.exe 从中生成一个类结构。我用值“填充”我的对象,但是在将其序列化为 XML 时,它会忽略所有不属于 string 类型的类属性。

var myGraph = new graph();
myGraph.myString = "hallo";
myGraph.myInt = 80;

var serializer = new XmlSerializer(typeof(graph));
TextWriter writeFileStream = new StreamWriter(Path.Combine(outFolder, outFile));
serializer.Serialize(writeFileStream, myGraph);
writeFileStream.Close();

我预计:

<graph xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
    myString="hallo" 
    myInt="80"
/>

实际输出为:

<graph xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    myString="hallo" 
/>

属性myInt 已被忽略。如果我将其定义为字符串,它也会出现,但与任何其他类型一样,它不会出现。如果我声明它required并保留它null,它将被序列化为myInt="0"

我错过了什么?

一些细节:

XSD:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="graph">
    <xs:complexType>
      <xs:attribute name="myString" type="xs:string" />
      <xs:attribute name="myInt" type="xs:int" />
    </xs:complexType>
  </xs:element>
</xs:schema>

生成的类:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=false)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class graph {
    private string myStringField;
    private int myIntField;

    [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
    public string myString {
        get { return this.myStringField; }
        set { this.myStringField = value; }
    }

    [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
    public int myInt {
        get { return this.myIntField; }
        set { this.myIntField = value; }
    }

    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool myIntSpecified {
        get { return this.myIntFieldSpecified; }
        set { this.myIntFieldSpecified = value; }
    }

【问题讨论】:

  • 在您发布的生成的类中,myIntSpecified 函数引用了 myIntFieldSpecified 变量,但我在类中的任何地方都没有看到该变量定义?

标签: c# attributes xmlserializer


【解决方案1】:

XSD 将为所有值类型的属性添加一个额外的“指定”字段。当使用带有值类型的 .NET 序列化时,您将始终需要指定字段的值并将匹配的“指定”属性设置为 true。

将您的代码更改为此,它将按预期工作:

var myGraph = new graph();
myGraph.myString = "hallo";
myGraph.myInt = 80;
myGraph.myIntSpecified = true;

【讨论】:

  • 嗯,我当然注意到了这个字段,并且在使用 xsd.exe 时我多次看到它。我只是没有想到,它必须设置为true“手动”。
  • 非常感谢您的提示,我为这个错误快疯了。我的老板会说“这是第一章——你应该知道这一点”。谢谢!
【解决方案2】:

我对此不是 100% 确定,但请记住类似的事情。 看到生成的“myIntSpecified”字段了吗?您应该将此设置为 true。

xsd.exe 有一些很大的限制,你可以用谷歌搜索替代方案,或者只是记住每次都将其设置为 true。 :)

【讨论】:

  • 嗯,我曾经使用svcutil.exe 而不是xsd.exe,但我在使用xs:attributes 时遇到了很多麻烦,它表明xsd.exe 更容易使用案子。在其他情况下,我仍然坚持svcutil.exe。感谢您的回复,如果我有更多的声望点,我会投票给您。
  • @Nylle:没问题,@pmartin 的解释很好。还有一个提示,您还可以使用CodeDomProvider、XmlSchemaImporter 和 XmlCodeExporter 为 CodeDOM 生成代码。之后您可以通过 CodeDOM 调整生成的代码。这可以让您在需要时对生成的代码进行额外控制。
【解决方案3】:

我的朋友,你身边还有其他事情要发生。我确实编译了代码,它运行良好:

类:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = false)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class graph
{
    private string myStringField;
    private int myIntField;

    [System.Xml.Serialization.XmlAttributeAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
    public string myString
    {
        get { return this.myStringField; }
        set { this.myStringField = value; }
    }

    [System.Xml.Serialization.XmlAttributeAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
    public int myInt
    {
        get { return this.myIntField; }
        set { this.myIntField = value; }
    }


}

代码:

    graph g = new graph() {myInt = 80, myString = "ali"};
    XmlSerializer xss = new XmlSerializer(typeof (graph));
    MemoryStream ms = new MemoryStream();
    xss.Serialize(ms, g);
    StreamReader sb = new StreamReader(ms);
    ms.Position = 0;
    Console.WriteLine(sb.ReadToEnd());

输出:

<graph xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org
/2001/XMLSchema-instance" myString="ali" myInt="80" />

【讨论】:

  • 我没有生成。我复制了他的课程,并编写了一个简单的测试工具。
  • @Aliostad - 您的课程(至少您在上面发布的课程)与原始帖子生成的课程不同。您在发布的课程中缺少 myIntSpecified 字段。
  • 是的,但那是什么? myIntFieldSpecified 尚未指定并且在您的课程中缺失。
  • @Aliostad - 我应该说你缺少 myIntSpecified 函数,而不是字段。我同意,原始生成的类中缺少该字段,我不知道为什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多