【问题标题】:How to put XElement Document records inside a list of objects如何将 XElement 文档记录放在对象列表中
【发布时间】:2013-12-06 15:39:55
【问题描述】:

我在 XDocument 中加载了以下 XML 文档

<XXXXXXXXXXXXXXXXXX xmlns:XXXXX="http://XXXXX/XXXXX/XXXXX/" xmlns:mbs="http://www.microsoft.com/xml">
  <ProdOrderRoutingLine xmlns="Prod. Order Routing Line" />
  <Count>2</Count>
  <Records>
    <Record>
      <Field>
        <Name xmlns="Name">Company-Company-Company-Company</Name>
        <Value xmlns="Value">CRONUS Canada, Inc.</Value>
        <FieldCaption xmlns="FieldCaption">Name</FieldCaption>
      </Field>
      <Field>
        <Name xmlns="Name">Operation No.</Name>
        <Value xmlns="Value">020</Value>
        <Caption xmlns="Caption">Operation No.</Caption>
      </Field>
      <Field>
        <Name xmlns="Name">Line No.</Name>
        <Value xmlns="Value">771521</Value>
        <Caption xmlns="Caption" />
      </Field>
     </Record>
    <Record>
      <Field>
        <Name xmlns="Name">Company-Company-Company-Company</Name>
        <Value xmlns="Value">CRONUS Canada, Inc.</Value>
        <FieldCaption xmlns="FieldCaption">Name</FieldCaption>
      </Field>
      <Field>
        <Name xmlns="Name">Operation No.</Name>
        <Value xmlns="Value">020</Value>
        <Caption xmlns="Caption">Operation No.</Caption>
      </Field>
      <Field>
        <Name xmlns="Name">Line No.</Name>
        <Value xmlns="Value">798122</Value>
        <Caption xmlns="Caption" />
      </Field>
    </Record>
  </Records>
</XXXXXXXXXXXXXXXXXX>

我正在尝试使用 LINQ 读取它并为每条记录填充此类

public class Record
{
    public IEnumerable<Field> Fields { get; set; }

    public Record()
    {
        Fields = new List<Field>();
    }
}
public class Field
{
    public string Name { get; set; }
    public string Value { get; set; }
    public string Caption { get; set; }
}

欢迎以任何适当的方式在我的集合中提供 XML。

我试着弄乱了:

var doc = XDocument.Load(@"c:\test\output.xml");

var query = from table in doc.Element("XXXXXXXXXXXXXXXXXX").Element("Records").Elements("Record")
    select new 
{
    name = table.Elements("Field").Attributes("Name"),
    value = table.Elements("Field").Attributes("Value"),
    caption = table.Elements("Field").Attributes("FieldCaption")
};

我没有得到任何接近我正在寻找的东西。

【问题讨论】:

  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 您了解 XML 命名空间是什么以及它的用途吗?那个文件有很多错误。
  • SO 而不是 Company-Company-Company-CompanyCRONUS Canada, Inc.名称我想要这个?
  • Company-Company-Company-CompanyCRONUS Canada, Inc.Name

标签: c# .net xml linq linq-to-xml


【解决方案1】:

我不会在这里介绍完整的血腥细节,但这是一个非常设计糟糕的 XML 文档。您或文档的设计者需要阅读 XML 标准,特别是名称空间。

文档中涉及命名空间。 Field 元素下的元素都是命名空间(我可能会添加不正确)。 Name 元素位于命名空间中:"Name"Value 在命名空间中:"Value"Caption 元素位于命名空间"Caption""FieldCaption" 中。您必须根据这些命名空间编写查询。

此方法有助于读取这些字段元素:

Field ReadField(XElement fieldElement)
{
    XNamespace nsName = "Name";
    XNamespace nsValue = "Value";
    XNamespace nsFieldCaption = "FieldCaption";
    XNamespace nsCaption = "Caption";
    return new Field
    {
        Name = (string)fieldElement.Element(nsName + "Name"),
        Value = (string)fieldElement.Element(nsValue + "Value"),
        // Try the Caption namespace, otherwise try FieldCaption
        Caption = (string)fieldElement.Element(nsCaption + "Caption") ?? (string)fieldElement.Element(nsFieldCaption + "FieldCaption"),
    };
}

那么你的查询就变成了这样:

var query =
    from record in doc.XPathSelectElements("/XXXXXXXXXXXXXXXXXX/Records/Record")
    select new Record
    {
        Fields = record.Elements("Field")
            .Select(f => ReadField(f))
            .ToList(),
    };

【讨论】:

  • 我没有创建那个 XML 文档,但我也许可以让他们更改它...你能给我一个它应该是什么样子的例子吗?
  • 据我所知,主要问题是添加到 Field 元素 (xmlns="...") 中的元素上的命名空间。这些是完全没有必要的。那些应该被删除。如果它们被删除,那么我们可以删除所有在 ReadField() 方法中使用的 XNamespace
【解决方案2】:

我认为您在正确的轨道上,但您的 LINQ 查询有问题。

我没有时间完全测试下面的例子,但下面看起来更接近一点:

        var result = from c in doc.Descendants("Records")
                        select new Record()
                        {
                            Fields = from f in c.Descendants("Field")
                                        select new Field() 
                                        {
                                            Name = f.Element("Name").Value,
                                            Value = f.Element("Value").Value,
                                            Caption = f.Element("FieldCaption").Value
                                        }
                        };

注意:以下链接似乎有有价值的信息:
Parse xml using LINQ to XML to class objects
How to get elements by name in XML using LINQ

祝你好运。

【讨论】:

    【解决方案3】:

    好的,使用上面的人提供的信息,我结束了

    1. 修复 XML 以规范化 Caption 和 FieldCaption 标签
    2. 删除了不需要的 XMLNS

    所以现在我的代码是这样的..

    public class Record
    {
        public List<Field> Fields { get; set; }
        public Record()
        {
            Fields = new List<Field>();
        }
    }
    
    public class Field
    {
        public string Name { get; set; }
        public string Value { get; set; }
        public string Caption { get; set; }
    
        public Field(){}
    }
    
    Field ReadField(XElement fieldElement)
    {
        return new Field{
            Name = (string)fieldElement.Element("Name"),
            Value = (string)fieldElement.Element("Value"),
            Caption = (string)fieldElement.Element("Caption")
        };
    }
    void Main()
    {
    
        var lstRecords = new List<Record>();    
    
        XDocument doc = XDocument.Load(@"c:\fred\output.xml");
    
    var query = from record in doc.XPathSelectElements("/XXXXXXXXXXXXXXXXXX/Records/Record")
    select new Record
        {
            Fields = record.Elements("Field").Select (f => ReadField(f)).ToList(),
        };
    
    query.Dump();
    
    }
    

    它完美地工作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-15
      • 1970-01-01
      • 2019-08-19
      • 2021-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多