1

我真正讨厌的是从 Xml 文件中转换每个元素或属性值。

此刻,我正在数百个模块中创建一个方法,其中指定如何将对象转换为 XmlFile。相信,这很累。所以我正在考虑另一种选择。

我正在调查 XSD,我不确定这是否会成为我的救赎。我正在使用 Linq to Xml 来保存和获取值。我的意思是,我的对象是这样组成的:

- Foo1 : Foo
   - Range1 : Range
      - X : int
      - Y : int
- ...

如您所见,它们有许多节点。还有另一种选择吗?我的意思是,强类型。

4

4 回答 4

1

您可以尝试这些 XElement 扩展方法:http ://searisen.com/xmllib/extensions.wiki

鉴于另一篇文章中的这个 xml,这是它的强大功能的一个示例:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <PatchCreation
    Id="224C316C-5894-4771-BABF-21A3AC1F75FF"
    CleanWorkingFolder="yes"
    OutputPath="patch.pcp"
    WholeFilesOnly="yes">
    <PatchInformation
        Description="Update Patch"
        Comments="Update Patch"
        ShortNames="no"
        Languages="1033"
        Compressed="yes"
        Manufacturer="me"/>

    <PatchMetadata
        AllowRemoval="yes"
        Description="Update Patch"
        ManufacturerName="me"
        TargetProductName="Update"
        MoreInfoURL="http://andrewherrick.com/"
        Classification="Update"
        DisplayName="Update Patch"/>

    <Family DiskId="5000"
        MediaSrcProp="Sample"
        Name="Update"
        SequenceStart="5000">
      <UpgradeImage SourceFile="c:\new.msi" Id="PatchUpgrade">
        <TargetImage SourceFile="c:\old.msi" Order="2" Id="PatchUpgrade" IgnoreMissingFiles="no" />
      </UpgradeImage>
    </Family>

    <PatchSequence PatchFamily="SamplePatchFamily"
        Sequence="1.0.0.0"
        Supersede="yes" />
  </PatchCreation>
</Wix>

这将设置 UpgradeImage 标记的 SourceFile 属性的值以及 UpgradeImage 及其 SourceFile 中的 TargetImage 标记。

XElement wix = XElement.Load(xmlFile1.FullName);
wix.Set("PatchCreation/Family/UpgradeImage/SourceFile", "upgrade path", true)
   .Set("TargetImage/SourceFile", "target path", true);

您也可以以相同的方式获取它们的值(无强制转换)。

string upgradeSource = wix.Get("PatchCreation/Family/UpgradeImage/SourceFile", string.Empty);
string targetSource = wix.Get("PatchCreation/Family/UpgradeImage/TargetImage/SourceFile", string.Empty);

或者这可以写成:

XElement upgradeImage = wix.GetElement("PatchCreation/Family/UpgradeImage");
string upgradeSource = upgradeImage.Get("SourceFile", string.Empty);
string targetSource = upgradeImage.Get("TargetImage/SourceFile", string.Empty);

要获取整数列表:

<root>
 <path>
  <list>
    <value>1</value>
    <value>12</value>
    <value>13</value>
    <value>14</value>
    <value>15</value>
   </list>
  </path>
</root>

使用 GetEnumerable() 方法:

List<int> list = root
    .GetEnumerable("path/list/value", xvalue => xvalue.Get(null, int.MinValue));
    .ToList();

要设置一个新的整数列表:

var list2 = new int[] { 1, 3, 4, 5, 6, 7, 8, 9, 0 };
root.SetEnumerable("path/list", list2, a => new XElement("value", a));

这导致了这个新的xml:

<root>
  <path>
    <list>
      <value>1</value>
      <value>3</value>
      <value>4</value>
      <value>5</value>
      <value>6</value>
      <value>7</value>
      <value>8</value>
      <value>9</value>
      <value>0</value>
    </list>
  </path>
</root>
于 2012-04-04T17:35:54.300 回答
0

最好的选择是使用 XmlSerialization。因此,序列化为 XML,然后反序列化为对象,那么您就不必使用强制转换了。

有时 XML 是通过序列化以外的其他方式创建的。然而,您仍然可以创建代表您的 XML 结构和反序列化的类。

例如:

Public Class Foo
{
   public Range Range {get; set;}
}


public class Range
{
    public int X {get; set;}
    public int Y {get; set;}
}

然后你用这个:

XmlSerializer ser = new XmlSerializer(typeof(Foo));
于 2012-04-04T16:13:03.387 回答
0

我经常使用 XSD 来验证 XML 结构,部分原因是因为我没有默认构造函数和/或私有字段,XMLSerialization因此通常也不是一个选项。

如果 XML 验证没有错误,那么我继续使用 Linq2Xml 并使用各种Parse(String s)方法来获取我的类所需类型的数据,但是我还没有找到一个干净的解决方案,它可以在没有任何类型的转换的情况下做到这一点。

验证步骤避免了由于数据类型不正确而导致的异常。

var query = from tst in xml.Elements("test")
            select new 
            {
                int1 = Int32.Parse(tst.Element("int1").Value), 
                double1 = Double.Parse(tst.Element("double1").Value), 
                double2 = Double.Parse(tst.Element("double2").Value), 
            }

编辑:添加信息以回复评论“

您可以直接从 Visual Studio GUI 创建 XSD,还有其他工具也可以这样做,但我通常只使用 Visual Studio。在编辑器中打开 XML,然后从 XML 菜单中选择“Create Schema”(路径显示在快照中)。

Visual Studio IDE 中的 XML 到 XSD

生成的 XSD 非常基础。它试图通过并“猜测”每个节点的适当数据类型,并且它不包含任何额外的限制,但它为您将框架组合在一起做得不错。

完成后,您可以进入并调整数据类型以更好地满足您的需求(如果需要),您可以为数据添加自己的限制(例如要求xs:int值在 0 到 50 的范围内或xs:string值长度小于 10 个字符 - 还有许多其他可能性,但这应该会给你这个想法)。

实际上,我只是在玩弄 XSD 语言,而且越做越容易。W3Schools网站非常宝贵。

于 2012-04-04T16:37:34.947 回答
0

我们使用Linq To Xsd围绕XDocument.

您只需编写一个模式文件 (Xsd) 并将其包含在您的项目中(一旦您将 LinqToXsd 破解到 csproj 文件中:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Foo1">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Range1">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="X" type="xs:int"/>
                            <xs:element name="Y" type="xs:int"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

然后你可以访问同名的类:

Foo1 foo = new Foo1()
{
    Range1 = new Foo1.Range1()
    {
        X = 7,
        Y = 10,
    }
};

foo.Save(foo.xml);

var input = Foo1.Load(input.xml);

Console.WriteLine(input.Range1.X.ToString());

J。

于 2012-08-02T09:01:19.360 回答