【问题标题】:Load xml data from web API to dataset and then get relational data from datatables to new data table将 xml 数据从 Web API 加载到数据集,然后从数据表中获取关系数据到新数据表
【发布时间】:2020-07-10 22:15:15
【问题描述】:

我是 C# 开发的新手,第一次在这里发帖,如果我发错地方或听起来很傻,请原谅我

我需要从我已经设法做到这一点的 Web API 中提取 xml 数据

var request = (HttpWebRequest)WebRequest.Create("webURLhere");
        request.Method = "GET";
        request.ContentType = "application/xml";
        request.Headers.Add("Authorization: Bearer Tokenvalue");
        TextReader reader = new StringReader(newStreamReader(request.GetResponse().GetResponseStream()).ReadToEnd());
        XElement xEle = XElement.Load(reader);

我现在被困在如何在 StreamReader 中实际利用这些数据

放弃使用 Streamreader 后,我下载了返回的 xml 文件,如下所示

<?xml version="1.0" encoding="utf-8"?>
<response status="ok">
<submissions>
    <submission>
        <id>12345</id>
        <timestamp>2020-06-02 09:20:49</timestamp>
        <user_agent>Mozilla/5.0</user_agent>
        <remote_addr>111.111.111.11</remote_addr>
        <payment_status></payment_status>
        <latitude>321</latitude>
        <longitude>123</longitude>
        <read>1</read>
        <data>
            <XML_Serializer_Tag>
                <field>91388567</field>
                <value>2723</value>
                <flat_value>2723</flat_value>
                <label>URN</label>
                <type>number</type>
            </XML_Serializer_Tag>
            <XML_Serializer_Tag>
                <field>1</field>
                <value>
                    <XML_Serializer_Tag>disclaimer</XML_Serializer_Tag>
                </value>
                <flat_value>disclaimer</flat_value>
                <label>Checkbox</label>
                <type>checkbox</type>
            </XML_Serializer_Tag>
            <XML_Serializer_Tag>
                <field>2</field>
                <value>12345</value>
                <flat_value>12345</flat_value>
                <label>ID</label>
                <type>number</type>
            </XML_Serializer_Tag>
            <XML_Serializer_Tag>
                <field>3</field>
                <value>Name</value>
                <flat_value>Name</flat_value>
                <label>Name</label>
                <type>text</type>
            </XML_Serializer_Tag>
            <XML_Serializer_Tag>
                <field>4</field>
                <value>email@email.com</value>
                <flat_value>email.email.com</flat_value>
                <label>Email</label>
                <type>email</type>
            </XML_Serializer_Tag>
            <XML_Serializer_Tag>
                <field>5</field>
                <value>filelink</value>
                <flat_value>filelink</flat_value>
                <label>OL1</label>
                <type>file</type>
            </XML_Serializer_Tag>
            <XML_Serializer_Tag>
                <field>6</field>
                <value>filelink</value>
                <flat_value>filelink</flat_value>
                <label>DC1</label>
                <type>file</type>
            </XML_Serializer_Tag>
            <XML_Serializer_Tag>
                <field>7</field>
                <value>filelink</value>
                <flat_value>filelink</flat_value>
                <label>DC2</label>
                <type>file</type>
            </XML_Serializer_Tag>
        </data>
    </submission>
</submissions>
<total>1</total>
<pages>1</pages>
<pretty_field_id>4321</pretty_field_id>

我已经设法通过这样做将这个 xml 数据从本地文件中获取到数据集中

DataSet ds = new DataSet();
ds.ReadXml(@"C:\All.XML", XmlReadMode.Auto);

DataSet 可视化工具向我显示数据,我可以通过在调试模式下查看数据集来查看数据集中的关系。我也可以通过这样做单独处理每个表

dt1 = ds.Tables[2];

但不能在表之间创建关系。

我需要根据关系将提交、数据和 XML_Serializer_Tag 表中的数据提取到一个 datagridview 中,但我今天一整天都无法到达任何地方。请帮忙....

***** 编辑 ********

好的,终于做到了。这是我的代码,将其发布在这里是因为我花了很长时间才弄明白,而且无限量的谷歌搜索没有给我结果。

        var submissions = xEle.Descendants("submission");
        int Srno = 0;
        foreach (var sub in submissions)
        {
            int rowId = dataGridView1.Rows.Add();
            DataGridViewRow row = dataGridView1.Rows[rowId];
            var sub_data = xEle.Descendants("submission").ElementAt(Srno).Descendants("data").Descendants("XML_Serializer_Tag");
            foreach (var SData in sub_data)
            {
                row.Cells["id"].Value = sub.Element("id").Value;
                row.Cells["timestamp"].Value = sub.Element("timestamp").Value;
                row.Cells["Srno"].Value = Srno + 1;
                row.Cells[SData.Element("label").Value].Value = SData.Element("value").Value;
            }
            Srno++;

这会从提交中返回每一行的数据,然后将与提交相关的所有内容从data.XML_Serializer_Tag逐行加载到datagridview中,使用Srno在datagridview中生成行号。

现在剩下的就是如何从“响应”中获取数据,我需要“总计”和“页面”

如果我在这里偏离了轨道,也请告诉我,并且可以采取不同的方式

【问题讨论】:

  • 对于复杂的 xml 文件,ReadXml 将提供无用的破碎数据。无法重新组合数据以使其有意义。

标签: c# xml


【解决方案1】:

这不会回答您的全部问题,但会帮助您使用来自 WebRequest 的响应流。

TextReader reader = new StringReader( new StreamReader( request.GetResponse().GetResponseStream() ).ReadToEnd() );
DataSet ds = new DataSet();
ds.ReadXml( reader, XmlReadMode.Auto );

或者,您可以尝试:

ds.ReadXml( request.GetResponse().GetResponseStream(), XmlReadMode.Auto );

虽然我更喜欢将事物分开(例如使用 TextReader)以帮助简化可读性和故障排除。

【讨论】:

  • 您尝试过您的解决方案吗?结果将为您提供没有意义的表格中的断裂数据。
  • 是的,我可以通过执行此 dataGridView1.DataSource = ds.Tables[2]; 在数据网格视图中查看每个表中的数据
【解决方案2】:

试试xml序列化

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Globalization;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(Response));
            Response response = (Response)serializer.Deserialize(reader);

            int Srno = 1;
            foreach (var sub in response.submission)
            { 
                Console.WriteLine("Row_number = '{0}', Id = '{1}', Date = '{2}'",  Srno++, sub.id, sub.timestamp); 
            }
            Console.ReadLine();
        }
    }
    [XmlRoot("response")]
    public class Response
    {
        [XmlAttribute("status")]
        public string status { get; set; }
        [XmlArray("submissions")]
        [XmlArrayItem("submission")]
        public List<Submission> submission { get; set; }
        public int total { get;set;}
        public int pages { get;set;}
        public int pretty_field_id { get;set;}
    }
    public class Submission
    {
        public int id { get; set; }
        private DateTime _timestamp { get; set; }

        public string timestamp
        {
            get { return _timestamp.ToString("yyyy-MM-dd HH:mm:ss"); }
            set { _timestamp = DateTime.ParseExact(value, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); }
        }

        public string user_agent { get; set; }
        public string remote_addr { get; set; }
        public string payment_status { get; set; }
        public int latitude { get; set; }
        public int longitude { get; set; }
        public int read { get; set; }

        [XmlArray("data")]
        [XmlArrayItem("XML_Serializer_Tag")]
        public List<Tag> tags { get; set; }
    }
    public class Tag
    {
        public int field { get; set; }
        [XmlElement("value")]
        public string _value { get; set; }
        public string flat_value { get; set; }
        public string label { get; set; }
        public string type { get; set; }
    }
}

【讨论】:

  • 非常感谢您提供如此详细的回复,正如我在问题中提到的,我对在 C# 中使用 xml 或开发完全陌生。我不确定如何使用它来获得我想要的结果。理想情况下,我想将 xml 中的每一行插入到 SQL 服务器表中。我可以在 SQL Server 中插入行,只需要知道我将如何遍历所有行,这样我就可以从每个 xml 节点获取一行数据。
  • 行在反序列化类中作为列表: public List submit { get;放;有很多解析xml的方法。我都使用它们。在这种情况下,从数据结构来看,我认为序列化是最好的方法。我可以使用 xml linq 从 xml 中获取每一行,但不知道您需要什么数据和格式,所以我选择了序列化并解析所有内容。所以使用 response.submission.Select(x => ...... (或循环)。
  • 我完全不知道如何使用你上面给我的代码,所以我找到了这个 XElement xEle = XElement.Load(@"C:\test.xml"); var 提交 = xEle.Descendants("提交"); int Srno = 0; foreach(提交中的 var sub){ Console.WriteLine("Row_number = " + Srno++ + " " + sub.Element("id").Value + ", " + sub.Element("timestamp").Value); } 其中列出了提交中的所有行,我想要每个提交的数据中的字段、标签和值。
  • 在c#中有很多不同的解析xml的方法。您发布的代码使用的是我经常使用的 linq xml。我的代码使用序列化,数据都在“响应”变量中。要获取每个提交,您可以使用 for 循环:foreach(Submission submit in response.submission)
  • 我更新了我的帖子,我设法得到了我想要的结果,那就是提交表中的一行数据和数据表中的所有行。
猜你喜欢
  • 1970-01-01
  • 2013-02-20
  • 2020-10-12
  • 2014-07-28
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 2019-06-30
  • 2012-05-17
相关资源
最近更新 更多