分享

XML与DataSet的互转

 kittywei 2011-12-02

XML与DataSet的互转

XML与DataSet进行交互是非常容易的,无论是XML文件还是XML字符串。而我们现在主要用的都是XML字符串的方式。即使用DataSet.GetXml()方式。

        一般来说,用DataSet生成的Xml格式应该是如下方式:
<NewDataSet>
    <Table>
        <Columns1>……</Columns1>
        <Columns2>……</Columns2>
    </Table>
    <Table>
        <Columns1>……</Columns1>
        <Columns2>……</Columns2>

    </Table>
    <Table1>
        ……
    </Table1>
</NewDataSet>
        上面是一个基本的格式的由DataSet转成的XML,其并不包含Schema。在VS.net的开发中,无论你是绑定XML,还是DataSet,效果都是一样的。
        现在我来解释一下DataSet生成XML的格式:
        应该可以看到,首先是根结点:<NewDataSet />  这个应该不用多说,再其下我们可以看到<Table />、<Table1 />等等这样的子结点。当在DataSet中只有一个表的时候,在XML中只会有<Table>结点,而当DataSet中有多个表的时候,在XML中会将这些Tabel表示出来,第1个表为<Table />,第2个表为<Table1 />,第3个表为<Table2 />…………。而且如何在一个表中具有多行的时候,每一行都会放到一个<Table />结点中。假如我们有一个表中有两个字段:ID与NAME,则按上述示例,在XML中的表示为:
<NewDataSet>
    <Table>
        <ID>ID1</ID>
        <NAME>NAME1</NAME>
    </Table>
    <Table>
        <ID>ID2</ID>
        <NAME>NAME2</NAME>

    </Table>
</NewDataSet>
        但是如果你足够细心去留意这些的话,就会发现,当在数据表中的某个字段为空值(即为null,而并非为”")时,其根本不会显示在XML上,这就造成了当需要对XML进行数据绑定的时候,根本无法找到该字段。而且我们也会发现,无论我们在数据库中存放的表是什么名字,在XML的显示中一律依次用<Table />、<Table1 />来代替,我们仅仅知道在每个表中的字段名称而已。还有第3点,在XML中所有的数据都是String类型的,不管是数字还是时间。这又该怎么办呢?
        当然,这就要归功于XmlSchema的功劳了。我将会在明天将第2部分–“Schema的作用”写出来。
上面提到了几个问题:
    1、当在数据表中的某个字段为空值(即为null,而并非为”")时,其根本不会显示在XML上,这就造成了当需要对XML进行数据绑定的时候,根本无法找到该字段。该如何解决?
    2、无论我们在数据库中存放的表是什么名字,在XML的显示中一律依次用<Table />、<Table1 />来代替,如何通过表名称来找呢?
    3、在XML中所有的数据都是String类型的,不管是数字还是时间。如何让Xml中的数据类型与DataSet中的一样?

    好,现在开始讲解Schema。我们可以通过DataSet.GetXmlSchema()来得到DataSet的Schema。当然,该方法还是用来生成String这符串的。我们首先来看一下它的格式。
    假如有如下表:
表Test,其字段描述如下:
ID(string) Name(string) time(DateTime)
1  aa  2004-5-1
2  bb  

其DataSet的Xml格式如下:
<?xml version=”1.0″ encoding=”utf-16″?>
<xs:schema id=”NewDataSet” xmlns=”" xmlns:xs=”
http://www./2001/XMLSchema” xmlns:msdata=”urn:schemas-microsoft-com:xml-msdata”>
  <xs:element name=”NewDataSet” msdata:IsDataSet=”true” msdata:Locale=”zh-CN”>
    <xs:complexType>
      <xs:choice maxOccurs=”unbounded”>
        <xs:element name=”test”>
          <xs:complexType>
            <xs:sequence>
              <xs:element name=”ID” type=”xs:string” minOccurs=”0″ />
              <xs:element name=”Name” type=”xs:string” minOccurs=”0″ />
              <xs:element name=”time” type=”xs:dateTime” minOccurs=”0″ />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

    至于Schema的写法,我就不多说了,不清楚的朋友可以找一本Xml的基础资料来看一下。这里我们重点要看红色标注的一行,里属性type就是用来表示在Xml中该字段的数据类型。其它属性还包含字段的限制等等。实际上,XmlSchema的作用就在于此。同时,即便在Xml中字段为空时不显示,通过XmlSchema也可以得到完整的数据字段。还有一点,就是表名,你同时也可以看到在XmlSchema中有与Xml中对应的表名,这里看到的为test。
    好,讲到这里,我想你已经大概了解DataSet转为Xml的一些基础知识了。那么现在我再来讲一下Xml还原成DataSet的方法。
    DataSet已经很好的支持了Xml。这一点我在开发过程中感受得非常深刻。DataSet通过客户端是不能够提取的,因此我先转成Xml,然后通过客户端的MSXML进行DOM解析,真的是非常棒哦。有空你也可以试一下它的强大功能。
    Xml转成DataSet主要用DataSet.ReadXmlSchema()和DataSet.ReadXml()方法。注意这里,我们通过DataSet获取时,如果要获取Schame,那么写一定要先将DataSet.ReadXmlSchema()写在前面,因为DataSet只有首先得到数据架构,才能在架构中添加数据哦(想想建筑师们是怎么设计的吧)!

     如果XML数据是DiffGram,那么就用DiffGram格式推导数据。如果XML文档包含内联架构,那么这个架构就用于确定DataSet对象的子元素的结构。这种行为等于ReadSchema选项。如果没有找到架构,那么就用InferXMLSchema方法从DataSet对象推导架构信息。如果载加载DataSet对象时设置一个明确的XmlReadMode方法,那么就可以改进性能。

       在DataSet.GetXml()方法中,会有第二个参数是用来设置Get方法。里面最有作用的就是DiffGram参数。它可以完整保存DataSet中的信息。加入该参数,你再观察一下DataSet生成的Xml,会发现从获取DataSet到对DataSet的记录操作变更全部都记录在Xml中了,这就是DiffGram的功劳。这样,即便我们把DataSet以Xml的方法传递到任何其它层,都可以进行有效的更新或还原了。

DiffGram格式

        DiffGram是一种XML序列化格式,它包括每一行的原始值和当前值。特别地,它包含带有原始值的行列表以及将所有更改组织在一起的最后一节。每一行都由一个为已标示符,用于两节DiffGram之间跟踪改变。下面的清单描述了DiffGram的结构,其中第一行被删除,第三行被修改并且插入了一个新行:

<diffgr:diffgram>
 <DataSetName>
  <Employees diffgr:id=”Employees1″ msdata:rowOrder=”0″>…</Employees>
  <Employees diffgr:id=”Employees3″ msdata:rowOrder=”2″>…</Employees>
  <Employees diffgr:id=”Employees4″ msdata:rowOrder=”3″ diffgr:hasChanges=”modified”>…</Employees>
  <Employees diffgr:id=”Employees5″ msdata:rowOrder=”4″>…</Employees>
  <Employees diffgr:id=”Employees6″ msdata:rowOrder=”5″>…</Employees>
  <Employees diffgr:id=”Employees7″ msdata:rowOrder=”6″>…</Employees>
  <Employees diffgr:id=”Employees8″ msdata:rowOrder=”7″>…</Employees>
  <Employees diffgr:id=”Employees9″ msdata:rowOrder=”8″>…</Employees>
  <Employees diffgr:id=”Employees10″ msdata:rowOrder=”9″ diffgr:hasChanges=”inserted”>…</Employees>
 </DataSetName>
 <diffgr:before>
  <Employees diffgr:id=”Employees2″ msdata:rowOrder=”1″>…</Employees>
  <Employees diffgr:id=”Employees4″ msdata:rowOrder=”3″>…</Employees>
 </diffgr:before>
</diffgr:diffgram>

<diffgr:diffgram>根节点友两个子节点。第一个是带有其当前内容的DataSet对象,包括新添加的行和修改的行,但是不包括删除的行。这种数据树根据DataSet对象命名。用DataSetName属性的到和设置DataSet对象名。第二个节点是以<diffgr:before>节点为根的树。这个树包含恢复DataSet对象原始状态的足够信息。例如,它仍然包含所有被删除的行和所有被修改行的原始内容。受改变影响的所有列都在<diffgr:before>子树种跟踪。

标示行

diffgr:id属性用于在当前行和原始行之间建立链接。diffgr:hasChanges属性可以很快找到那些纪录被删除、插入或者只是修改。

你可以用另外两个属性来控制所保存的XML格式。第一个是DataColumn对象的ColumnMapping属性,它可以指定WriteXml方法是否隐藏了列,是将列写成一个元素、一个属性还是简单的文本。另一个你应该注意的属性就是DataRelation对象的Nested属性。当我们用WriteXml来写父子关系中子表里的记录时,该属性可以指定这些记录是否是嵌套在相关的父表记录中的。

注意:在试图从一个XML DiffGram创建DataSet对象时,要保证目标DataSet对象有与所读取得DataSet对象有同样的架构。不能将DiffGram装入一个空的新创建的DataSet对象。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多