【问题标题】:Need help retrieving XML data using Linq需要帮助使用 Linq 检索 XML 数据
【发布时间】:2017-10-04 19:41:04
【问题描述】:

我正在尝试从 XML 文件中检索数据并在列表中返回已解析的数据。根据我用来访问数据的内容(元素或属性),我要么得到 null(在元素的情况下),要么得到我无法破译的东西(在属性的情况下)。

XML 看起来像这样:

<DATA_RESPONSE>
    <HEADER>
        <MSGID>IS20101P:091317125610:98::34:0</MSGID>
    </HEADER>
    <DATA>
        <ROW ID='IS20101P' PE_NAME='APP-029' PE_ID='4' CODE='4829' DATA='5,1,500,1'  />
        <ROW ID='IS20101P' PE_NAME='APPS-029' PE_ID='4' CODE='4829' DATA='4,1,500,1' />
        ...
    </DATA>
    <SUMMARY>
    </SUMMARY>
    <ERRORS>
    </ERRORS>
</DATA_RESPONSE>

我正在使用以下内容来获取数据。我读取文件并将 XML 存储在一个字符串中,并以该字符串作为参数调用一个方法:

public static Hashtable GetIDSData(string sXMLString)
{
    Hashtable result = new Hashtable();

    result.Add("Success", false);
    result.Add("ErrorMessage", "");
    result.Add("ID", "");
    result.Add("PE_NAME", "");
    result.Add("PE_ID", "");
    result.Add("CODE", "");
    result.Add("DATA", "");

    xmlDoc.InnerXml = sXMLString;
    XmlElement root = xmlDoc.DocumentElement;
    XDocument doc = XDocument.Parse(sXMLString);
    XmlNode node = xmlDoc.SelectSingleNode("DATA_RESPONSE/DATA"); 

    if (node != null)
    {
        var AddressInfoList = doc.Root.Descendants("ROW").Select(Address => new
        {
            ID = Address.Attributes("ID")?.ToString(),
            PEName = Address.Attributes("PE_NAME")?.ToString(),
            PEID = Address.Attributes("PE_ID")?.ToString(),
            Code = Address.Attributes("CODE")?.ToString(),
            Data = Address.Attributes("DATA")?.ToString(),
        }).ToList();

        foreach (var AddressInfo in AddressInfoList)
        {
            if (string.IsNullOrEmpty(AddressInfo.Code))
            {
                result["Success"] = false;
                result["ErrorMessage"] = "Invalid Code; code is empty.";
            }
            else
            {
                result["Success"] = true;
                result["ErrorMessage"] = "";
                result["ID"] = AddressInfo.ID;
                result["PE_NAME"] = AddressInfo.PEName;
                result["PE_ID"] = AddressInfo.PEID;
                result["CODE"] = AddressInfo.Code;
                result["DATA"] = AddressInfo.Data;
            }
        }
        return result;
    }

在 Linq 部分,如果我使用 Address.Element("ID").Value,我会返回 null。 XML 中没有使用命名空间。

【问题讨论】:

    标签: c# asp.net linq xml-parsing


    【解决方案1】:

    首先,GetIDSData() 方法无法按原样编译,因为在 xmlDoc.InnerXml = sXMLString 行,xmlDoc 尚未定义。

    我假设您希望 xmlDoc 成为加载了 sXMLString 参数内容的 XmlDocument,所以我将该行更改为:

    XmlDocument xmlDoc = new XmlDocument {InnerXml = sXMLString};
    

    此外,您的 root 变量从未使用过,因此为了清楚起见,我将其删除。

    现在至于您问题的主要部分,鉴于您当前的语法,您正在对 collection 属性调用 .ToString(),这显然不是您想要的。要解决此问题,当您迭代 AddressInfoList 时,您需要获取如下属性值:

    ID = Address.Attributes("ID")?.Single().Value
    

    ID = address.Attribute("ID")?.Value
    

    ...而不是上面提到的Address.Attributes("ID")?.ToString()

    【讨论】:

    • Paul 和 Yuri 的建议都奏效了。 Paul 的变化最少,而且在 Yuri 的解决方案中,它抱怨 c 是 !string.IsNullOrEmpty(c) 中的一个字符。我希望我可以将两者都标记为解决方案,也许 SOF 可能会考虑。
    【解决方案2】:

    您没有选择属性值。在您的代码中,您正在选择属性。不确定您要实现什么,但这是我修改后的代码版本,可将所有元素加载到 DataTable 中

    public static DataTable GetIDSData(string sXMLString)
    {
      DataTable result = new DataTable();
    
    result.Columns.Add("Success");
    result.Columns.Add("ErrorMessage");
    result.Columns.Add("ID");
    result.Columns.Add("PE_NAME");
    result.Columns.Add("PE_ID");
    result.Columns.Add("CODE");
    result.Columns.Add("DATA");
    
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.InnerXml = sXMLString;
    XmlElement root = xmlDoc.DocumentElement;
    XDocument doc = XDocument.Parse(sXMLString);
    XmlNode node = xmlDoc.SelectSingleNode("DATA_RESPONSE/DATA");
    
    if (node != null)
    {
        var AddressInfoList = doc.Root.Descendants("ROW").Select(Address => new
        {
            ID = Address.Attributes("ID").Select(i=>i.Value) ,
            PEName = Address.Attributes("PE_NAME").Select(i=>i.Value),
            PEID = Address.Attributes("PE_ID").Select(i=>i.Value),
            Code = Address.Attributes("CODE").Select(i=>i.Value),
            Data = Address.Attributes("DATA").Select(i=>i.Value),
        }).ToList();
    
    
    
        AddressInfoList.ForEach(e => 
        {
            e.Code.ToList().ForEach(c =>
            {
                DataRow row = result.NewRow();
                if (!string.IsNullOrEmpty(c))
                {
    
                    row["Success"] = true;
                    row["ErrorMessage"] = "";
                    row["ID"] = e.ID.First();
                    row["PE_NAME"] = e.PEName.First();
                    row["PE_ID"] = e.PEID.First();
                    row["CODE"] = e.Code.First();
                    row["DATA"] = e.Data.First();
    
                }
                else
                {
                    row["Success"] = false;
                    row["ErrorMessage"] = "Invalid Code; code is empty.";
                }
                result.Rows.Add(row);
    
        });});
        result.Dump();
        return result;
    }
    return result;
    

    }

    这是您将在数据表中获得的结果。

    【讨论】:

      【解决方案3】:
      ID = Address.Attributes("ID")?.ToString(),
      

      您想改用Attribute(name)(不带s):

      ID = Address.Attributes("ID")?.Value,
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-08
        • 1970-01-01
        • 1970-01-01
        • 2019-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多