将XML读取到具有文件中多个表的DataSet

问题描述:

我正在为个人项目构建XML编辑器。使用WinForms DataGridView控制和DataSet,我能够设置阅读/编辑/保存没有什么问题,每个类型使用一个单独的XML文件。将XML读取到具有文件中多个表的DataSet

但是,当我开始尝试添加更多“高级”控件时,使用几个不同的文件变得很麻烦 - 需要if语句,这取决于我正在使用哪个文件。所以,我想这些文件合并成一个更大的文件,如下图所示:

<?xml version="1.0" encoding="utf-8" ?> 
<Items> 
    <Armor> 
    <Item> 
     <Name>Test Armor</Name> 
     <Value>1234567</Value> 
     <Rarity>Common</Rarity> 
     <Slot>Chest</Slot> 
     <Damage>1234567</Damage> 
     <Defense>1234567</Defense> 
     <Health>1234567</Health> 
     <Mana>1234567</Mana> 
     <Strength>1234567</Strength> 
     <Dexterity>1234567</Dexterity> 
     <FlavorText>Something about stuff</FlavorText> 
     <ImageSource>C:\Items\img.gif</ImageSource> 
    </Item> 
    </Armor> 
    <Consumables> 
    <Item> 
     <Name>Test Potion</Name> 
     <Value>1234567</Value> 
     <Damage>1234567</Damage> 
     <Defense>1234567</Defense> 
     <Health>0.1234567</Health> 
     <Mana>0.1234567</Mana> 
     <Strength>1234567</Strength> 
     <Dexterity>1234567</Dexterity> 
     <FlavorText>Something about stuff</FlavorText> 
     <ImageSource>C:\Items\img.gif</ImageSource> 
    </Item> 
    </Consumables> 
    <Junk> 
    <Item> 
     <Name>Test Junk</Name> 
     <Value>1234567</Value> 
     <Stackable>Yes</Stackable> 
     <FlavorText>Something about stuff</FlavorText> 
     <ImageSource>C:\Items\img.gif</ImageSource> 
    </Item> 
    </Junk> 
    <QuestItems> 
    <Item> 
     <Name>Test Quest Item</Name> 
     <Stackable>Yes</Stackable> 
     <FlavorText>Something about stuff</FlavorText> 
     <ImageSource>C:\Items\img.gif</ImageSource> 
    </Item> 
    </QuestItems> 
    <Weapons> 
    <Item> 
     <Name>Test Weapon</Name> 
     <Value>1234567</Value> 
     <Rarity>Common</Rarity> 
     <Slot>Primary</Slot> 
     <Damage>1234567</Damage> 
     <Defense>1234567</Defense> 
     <Health>1234567</Health> 
     <Mana>1234567</Mana> 
     <Strength>1234567</Strength> 
     <Dexterity>1234567</Dexterity> 
     <FlavorText>Something about stuff</FlavorText> 
     <ImageSource>C:\Items\img.gif</ImageSource> 
    </Item>  
    </Weapons> 
</Items> 

和模式,从Visual Studio的Create Schema菜单生成,最低限度修饰的 - 如改变unsignedIntint

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="Items"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element name="Armor"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element name="Item" maxOccurs="unbounded"> 
       <xs:complexType> 
        <xs:sequence> 
        <xs:element name="Name" type="xs:string" /> 
        <xs:element name="Value" type="xs:int" /> 
        <xs:element name="Rarity" type="xs:string" /> 
        <xs:element name="Slot" type="xs:string" /> 
        <xs:element name="Damage" type="xs:int" /> 
        <xs:element name="Defense" type="xs:int" /> 
        <xs:element name="Health" type="xs:int" /> 
        <xs:element name="Mana" type="xs:int" /> 
        <xs:element name="Strength" type="xs:int" /> 
        <xs:element name="Dexterity" type="xs:int" /> 
        <xs:element name="FlavorText" type="xs:string" /> 
        <xs:element name="ImageSource" type="xs:string" /> 
        </xs:sequence> 
       </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
     <xs:element name="Consumables"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element name="Item" maxOccurs="unbounded"> 
       <xs:complexType> 
        <xs:sequence> 
        <xs:element name="Name" type="xs:string" /> 
        <xs:element name="Value" type="xs:int" /> 
        <xs:element name="Damage" type="xs:int" /> 
        <xs:element name="Defense" type="xs:int" /> 
        <xs:element name="Health" type="xs:decimal" /> 
        <xs:element name="Mana" type="xs:decimal" /> 
        <xs:element name="Strength" type="xs:int" /> 
        <xs:element name="Dexterity" type="xs:int" /> 
        <xs:element name="FlavorText" type="xs:string" /> 
        <xs:element name="ImageSource" type="xs:string" /> 
        </xs:sequence> 
       </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
     <xs:element name="Junk"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element name="Item" maxOccurs="unbounded"> 
       <xs:complexType> 
        <xs:sequence> 
        <xs:element name="Name" type="xs:string" /> 
        <xs:element name="Value" type="xs:int" /> 
        <xs:element name="Stackable" type="xs:string" /> 
        <xs:element name="FlavorText" type="xs:string" /> 
        <xs:element name="ImageSource" type="xs:string" /> 
        </xs:sequence> 
       </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
     <xs:element name="QuestItems"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element name="Item" maxOccurs="unbounded"> 
       <xs:complexType> 
        <xs:sequence> 
        <xs:element name="Name" type="xs:string" /> 
        <xs:element name="Stackable" type="xs:string" /> 
        <xs:element name="FlavorText" type="xs:string" /> 
        <xs:element name="ImageSource" type="xs:string" /> 
        </xs:sequence> 
       </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
     <xs:element name="Weapons"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element name="Item" maxOccurs="unbounded"> 
       <xs:complexType> 
        <xs:sequence> 
        <xs:element name="Name" type="xs:string" /> 
        <xs:element name="Value" type="xs:int" /> 
        <xs:element name="Rarity" type="xs:string" /> 
        <xs:element name="Slot" type="xs:string" /> 
        <xs:element name="Damage" type="xs:int" /> 
        <xs:element name="Defense" type="xs:int" /> 
        <xs:element name="Health" type="xs:int" /> 
        <xs:element name="Mana" type="xs:int" /> 
        <xs:element name="Strength" type="xs:int" /> 
        <xs:element name="Dexterity" type="xs:int" /> 
        <xs:element name="FlavorText" type="xs:string" /> 
        <xs:element name="ImageSource" type="xs:string" /> 
        </xs:sequence> 
       </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

这两个文件都完全代表他们的同行 - 我有单独的文件ArmorConsumables

预期的结果是有一个文件代表以前分开的文件,例如:

Itemsroot节点。
Items之内的是父节点 - ArmorConsumables
在每个父节点内有子节点Item及其属性。

据我所知,XML结构和模式看起来是正确的,但是当我尝试将此文件读入我的程序时,我收到错误:System.FormatException - "Input string was not in a correct format."

堆栈跟踪显示System.Number.StringToNumber正在抛出此异常。我已经遍历了文件和模式几次,似乎无法找到发生的位置,异常详细信息不提供更多的细节。

在我的代码,我读简单地使用

DataSet data = new DataSet();    

data.ReadXmlSchema(itemSchema); 
data.ReadXml(itemData); 

这个确切的方法的工作没有问题,当文件/架构是分开的,这进一步使我相信,我简单地忽略了什么数据XML/Schema。

在这一点上,我卡住了,不知道它可能是什么。如果有人能帮我解决这个问题,我将不胜感激。

问题在于您重复每个项目类型的元素Item。 当您的代码读取模式时,它会找到Item元素的第一个外观,并尝试将相同模式应用于其他每个外观;所以,当它读取Test Potion它试图读取它作为stringintstringstringintintintintintintstringstring并且当它发现0.1234567 Health值失败。

我的建议是你的架构改变它的东西是这样的:

<?xml version="1.0" encoding="utf-8" ?> 
<Items> 
    <Armor> 
    <ArmorItem> 
    ...Item elements 
    </ArmorItem> 
    </Armor> 
    <Consumables> 
    <ConsumableItem> 
    ...Item elements 
    </ConsumableItem> 
    </Consumables> 
    <Junk> 
    <JunkItem> 
    ...Item elements 
    </JunkItem> 
    </Junk> 
    <QuestItems> 
    <QuestItem> 
    ...Item elements 
    </QuestItem> 
    </QuestItems> 
    <Weapons> 
    <WeaponItem> 
    ...Item elements 
    </WeaponItem>  
    </Weapons> 
</Items> 
+0

这实际上使真正的好感觉!我没有想到这一点。 – levelonehuman

+0

aaand它的工作完美。感谢您指出了这一点。学到了新东西! – levelonehuman