代码之家  ›  专栏  ›  技术社区  ›  CJM

正在分析XML文件-选项?

  •  1
  • CJM  · 技术社区  · 15 年前

    我正在开发一个系统,通过Exchange Web服务从电子邮件中提取XML附件,并通过我创建的自定义DAL对象将其输入数据库。

    我已经设法提取了XML附件,并将其作为流准备就绪…他们的问题是如何解析此流并填充DAL对象。

    我可以创建一个xmlTextReader并遍历每个元素。除此之外,我没有看到其他问题,我怀疑有一种更巧妙的方法。读卡器似乎将开始标记、标记内容和结束标记视为不同的元素(使用reader.nodeType)。我希望我的值是一个元素而不是三个元素。就像我说的,我可以解决这个问题,但我相信一定有更好的方法。

    我想到了使用XML序列化程序的想法(对我来说是全新的),但一个快速的浏览表明,这些程序无法处理数组列表和列表(我使用的是列表)。

    同样,我对Linq还不熟悉,但也提到了Linq to XML,但我看到的示例似乎相当复杂——尽管我只是缺乏熟悉。

    基本上,我不想有一个系统,但我不想使用任何复杂的技术和学习曲线,只是因为它是'酷'。

    将此XML/流转换为我的DAL对象的最简单和最有效的方法是什么?

    XML示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <enquiry>
        <enquiryno>100001</enquiryno>
        <companyname>myco</companyname>
        <typeofbusiness>dunno</typeofbusiness>
        <companyregno>ABC123</companyregno>
        <postcode>12345</postcode>
        <contactemail>me@example.com</contactemail>
        <firstname>My</firstname>
        <lastname>Name</lastname>
        <vehicles>
            <vehicle>
                <vehiclereg>54321</vehiclereg>
                <vehicletype>Car</vehicletype>
                <vehiclemake>Ford</vehiclemake>
                <cabtype>n/a</cabtype>
                <powerbhp>130</powerbhp>
                <registrationdate>01/01/2003</registrationdate>
            </vehicle>
        </vehicles>
    </enquiry>
    

    更新1 : 我正试图根据格雷厄姆的例子反序列化。我 认为 我已经为序列化设置了DAL,包括指定 [XmlElement("whatever")] 对于每个财产。我尝试使用以下方法反序列化:

    SalesEnquiry enquiry = null;
    XmlSerializer serializer = new XmlSerializer(typeof(SalesEnquiry));
    enquiry = (SalesEnquiry)serializer.Deserialize(stream);
    

    但是,我得到一个例外: There is an error in XML document (2, 2) '.内感受状态 {"<enquiry xmlns=''> was not expected."}

    结论 (更新):

    我以前的问题是XML文件中的元素(查询)!=类的名称(salesenquiry)。而不是 [XmlElement] 类的属性,我们需要 [XmlRoot] 改为属性。为了完整性起见,如果希望在序列化期间忽略类中的属性,请使用 [XmlIgnore] 属性。

    我已经成功地序列化了我的对象,现在已经成功地获取了传入的XML并将其反序列化为salesenquiry对象。

    这种方法比手动解析XML容易得多。好吧,有一个陡峭的学习曲线,但它是值得的。

    谢谢!

    3 回复  |  直到 15 年前
        1
  •  6
  •   Graham Clark    15 年前

    如果您的XML使用一个模式(即您总是要知道哪些元素出现在树中,以及它们出现在树中的位置),那么您可以使用 XmlSerializer 创建对象。您只需要类上的一些属性来告诉序列化程序它们对应的XML元素或属性。然后加载XML,创建一个新的 XML串行化器 使用要创建的.NET对象的类型,并调用 Deserialize 方法。

    例如,您有一个这样的类:

    [Serializable]
    public class Person
    {
        [XmlElement("PersonName")]
        public string Name { get; set; }
    
        [XmlElement("PersonAge")]
        public int Age { get; set; }
    
        [XmlArrayItem("Child")]
        public List<string> Children { get; set; }
    }
    

    和这样的输入XML(保存在本例的文件中):

    <?xml version="1.0"?>
    <Person>
      <PersonName>Bob</PersonName>
      <PersonAge>35</PersonAge>
      <Children>
        <Child>Chris</Child>
        <Child>Alice</Child>
      </Children>
    </Person>
    

    然后创建一个 Person 实例如下:

    Person person = null;
    XmlSerializer serializer = new XmlSerializer(typeof(Person));
    using (FileStream fs = new FileStream(GetFileName(), FileMode.Open))
    {
        person = (Person)serializer.Deserialize(fs);
    }
    

    更新: 根据您上次的更新,我想您需要指定 XmlRoot 作为根元素的类(即 SalesEnquiry ) XML串行化器 在XML中引用空命名空间可能有点困惑( xmlns='' 似乎不对)。

        2
  •  2
  •   tenfour    15 年前

    XmlSerializer不支持数组和列表…只要包含的类型是可序列化的。

        3
  •  1
  •   devuxer    15 年前

    我发现XSD2code对于这类事情非常有用: http://xsd2code.codeplex.com/

    基本上,您所需要做的就是编写一个XSD文件(一个XML模式文件)并指定一些命令行开关。XSD2code将自动生成一个C类文件,其中包含所有类和属性以及处理序列化所需的所有内容。这不是一个完美的解决方案,因为它不支持XSD的所有方面,但是如果您的XML文件是元素和属性的相对简单的集合,那么它对您来说应该是一个很好的捷径。

    在codeplex上还有一个类似的项目叫做linq to xsd( http://linqtoxsd.codeplex.com/ 这是为了强制执行整个XSD规范而设计的,但上次我检查时,它不再受支持,也没有真正准备好迎接黄金时段。不过,我觉得值得一提。