【问题标题】:How to convert many-to-one XML data to DataSet?如何将多对一的 XML 数据转换为 DataSet?
【发布时间】:2010-05-19 19:42:37
【问题描述】:

我有一个包含对象集合的 XML 文档。每个对象都有一个标签和值的键/值对。我正在尝试将其转换为 DataSet,但是当我执行 ds.ReadXml(xmlFile) 时,它会创建两列:标签和值。

我想要的是为每个“标签”设置一列,并将值作为行的一部分。这是我的 XML 示例:

<responses>
  <response>
    <properties id="1" Form="Account Request" Date="Tuesday, March 16, 2010 5:04:26 PM" Confirmation="True" />
    <fields>
      <field>
        <label>Name</label>
        <value>John</value>
      </field>
      <field>
        <label>Email</label>
        <value>John@Doe.com</value>
      </field>
      <field>
        <label>Website</label>
        <value>http://domain1.com</value>
      </field>
      <field>
        <label>Phone</label>
        <value>999-999-9999</value>
      </field>
      <field>
        <label>Place of Birth</label>
        <value>Earth</value>
      </field>
      <field>
        <label>Misc</label>
        <value>Misc</value>
      </field>
      <field>
        <label>Comments</label>
        <value />
      </field>
      <field>
        <label>Agree to Terms?</label>
        <value>True</value>
      </field>
    </fields>
  </response>
  <response>
    <properties id="2" Form="Account Request" Date="Tuesday, March 17, 2010 5:04:26 PM" Confirmation="True" />
    <fields>
      <field>
        <label>Name</label>
        <value>John2</value>
      </field>
      <field>
        <label>Email</label>
        <value>John2@Doe.com</value>
      </field>
      <field>
        <label>Website</label>
        <value>http://domain2.com</value>
      </field>
      <field>
        <label>Phone</label>
        <value>999-999-9999</value>
      </field>
      <field>
        <label>Place of Birth</label>
        <value>Earth</value>
      </field>
      <field>
        <label>Misc</label>
        <value>Misc</value>
      </field>
      <field>
        <label>Comments</label>
        <value />
      </field>
      <field>
        <label>Agree to Terms?</label>
        <value>True</value>
      </field>
    </fields>
  </response>
  <response>
    <properties id="3" Form="Account Request" Date="Tuesday, March 18, 2010 5:04:26 PM" Confirmation="True" />
    <fields>
      <field>
        <label>Name</label>
        <value>John3</value>
      </field>
      <field>
        <label>Email</label>
        <value>John3@Doe.com</value>
      </field>
      <field>
        <label>Website</label>
        <value>http://domain3.com</value>
      </field>
      <field>
        <label>Phone</label>
        <value>999-999-9999</value>
      </field>
      <field>
        <label>Place of Birth</label>
        <value>Earth</value>
      </field>
      <field>
        <label>Misc</label>
        <value>Misc</value>
      </field>
      <field>
        <label>Comments</label>
        <value />
      </field>
      <field>
        <label>Agree to Terms?</label>
        <value>True</value>
      </field>
    </fields>
  </response>
  <response>
    <properties id="4" Form="Account Request" Date="Tuesday, March 19, 2010 5:04:26 PM" Confirmation="True" />
    <fields>
      <field>
        <label>Name</label>
        <value>John</value>
      </field>
      <field>
        <label>Email</label>
        <value>John4@Doe.com</value>
      </field>
      <field>
        <label>Website</label>
        <value>http://domain4.com</value>
      </field>
      <field>
        <label>Phone</label>
        <value>999-999-9999</value>
      </field>
      <field>
        <label>Place of Birth</label>
        <value>Earth</value>
      </field>
      <field>
        <label>Misc</label>
        <value>Misc</value>
      </field>
      <field>
        <label>Comments</label>
        <value />
      </field>
      <field>
        <label>Agree to Terms?</label>
        <value>True</value>
      </field>
    </fields>
  </response>
</responses>

如何将其转换为 DataSet,以便将其加载到包含以下列的网格视图中:姓名、电子邮件、网站、电话、出生地、杂项、评论和同意条款?

那么第 1 行将是: John, John@Doe.com, http://domain1.com, 999-999-9999, Earth, Misc, , True

如何使用提供的 XML 执行此操作?

【问题讨论】:

    标签: c# asp.net xml .net-3.5 dataset


    【解决方案1】:

    您必须转换数据才能以您想要的方式使用它。如您所见,您的结构很糟糕。

    我建议您在 Visual Studio 中创建一个空数据集(从 Add->New Item),然后将其设置为您希望的样子。编写一些代码来添加一些测试数据,然后使用 DataSet.WriteXml 将其写入文件。这将向您展示您提议的结构是什么样的。

    然后我建议您使用 LINQ to XML 将输入的 XML 转换为新格式。


    以下是使用 LINQ to XML 转换数据的示例:

    public static void TransformIt(TextWriter output)
    {
        var inputDocument = XDocument.Parse(INPUT_XML);
        if (inputDocument.Root == null)
        {
            return;
        }
    
        var doc = new XDocument(
            new XElement(
                "responses",
                from response in inputDocument.Root.Elements()
                select new XElement(
                    "response",
                    from lv in GetResponseLabels(response)
                    select MakeResponse(lv.Label, lv.Value))));
    
        var settings = new XmlWriterSettings
        {
            Encoding = Encoding.UTF8,
            Indent = true,
        };
        using (var writer = XmlWriter.Create(output, settings))
        {
            if (writer == null)
            {
                return;
            }
    
            doc.WriteTo(writer);
        }
    }
    
    private static XElement MakeResponse(string label, string value)
    {
        var trimmedLabel = label.Replace(" ", String.Empty).Replace("?", String.Empty);
        return new XElement(trimmedLabel, value);
    }
    
    private static IEnumerable<LabelAndValue> GetResponseLabels(XContainer response)
    {
        var fieldsElement = response.Element("fields");
        if (fieldsElement == null)
        {
            return null;
        }
    
        return from field in fieldsElement.Elements("field")
               let valueElement = field.Element("value")
               let labelElement = field.Element("label")
               select new LabelAndValue
               {
                   Label = labelElement == null ? "Unknown" : labelElement.Value,
                   Value = valueElement == null ? null : valueElement.Value
               };
    }
    
    private struct LabelAndValue
    {
        public string Label { get; set; }
        public string Value { get; set; }
    }
    

    【讨论】:

      【解决方案2】:

      我将遍历 XML,并根据您的迭代方式(Linq 最灵活),使用您需要的方式描述的数据创建一个新对象(例如数据表)。

      【讨论】:

        【解决方案3】:

        我最终改变了一些方法并做到了这一点(枢轴):

        DataRow dr = dt.NewRow();
        
        //TRANSFORM RESPONSE LABELS INTO COLUMNS
        foreach (XmlNode fieldNode in currentXml.SelectNodes("response/fields/field"))
        {
            string label = fieldNode.SelectSingleNode("label").InnerText ?? "Unknown";
            string value = fieldNode.SelectSingleNode("value").InnerText;
            //CHECK IF ARBITRARY LABEL WAS ADDED BEFORE
            if (!dt.Columns.Contains(label))
            {
                //CREATE COLUMN FOR NEW LABEL
                dt.Columns.Add(label);
            }
            dr[label] = value;
        }
        dt.Rows.Add(dr);
        }
        ds.Tables.Add(dt);
        

        【讨论】:

          猜你喜欢
          • 2020-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-07-28
          • 1970-01-01
          • 2011-04-01
          • 2010-10-06
          相关资源
          最近更新 更多