簡體   English   中英

使用LINQ查詢XDocument,如何獲取特定值?

[英]Using LINQ to query XDocument, how to get specific values?

我正在嘗試重構以下內容-可以,但是如果我開始在XML中獲取更多元素,它將變得難以管理:

HttpResponseMessage response = await httpClient.GetAsync("https://uri/products.xml");

string responseAsString = await response.Content.ReadAsStringAsync();

List<Product> productList = new List<Product>();

XDocument xdocument = XDocument.Parse(responseAsString);
var products = xdocument.Descendants().Where(p => p.Name.LocalName == "item");

foreach(var product in products)
{
    var thisProduct = new Product();
    foreach (XElement el in product.Nodes())
    {
        if(el.Name.LocalName == "id")
        {
            thisProduct.SKU = el.Value.Replace("-master", "");
        }
        if (el.Name.LocalName == "availability")
        {
            thisProduct.Availability = el.Value == "in stock";
        }
    }
    productList.Add(thisProduct);
}

給定以下XML URL

<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns="http://base.google.com/ns/1.0" version="0">
    <channel>
        <title>Product Feed</title>
        <link></link>
        <description>Products</description>
        <item>
            <availability>in stock</availability>
            <id>01234-master</id>
            ...
        </item>
        <item>
            <availability>in stock</availability>
            <id>abcde-master</id>
            ...
        </item>
    </channel>
</rss>

理想情況下,我想刪除循環和if語句,並有一個LINQ查詢,該查詢以一種簡潔的方式僅從XML返回我需要的字段(id,可用性等),並用此數據填充一個簡單的類。

有人可以幫忙嗎?

有時您必須為編寫的代碼感到高興。 有時沒有“更智能”的編寫方式……您只能稍微“更好”地編寫它:

List<Product> productList = new List<Product>();

XDocument xdocument = XDocument.Parse(responseAsString);

XNamespace ns = "http://base.google.com/ns/1.0";

var products = from x in xdocument.Elements(ns + "rss")
               from y in x.Elements(ns + "channel")
               from z in y.Elements(ns + "item")
               select z;

foreach (var product in products)
{
    var prod = new Product();
    productList.Add(prod);

    foreach (XElement el in product.Elements())
    {
        if (el.Name == ns + "id")
        {
            prod.SKU = el.Value.Replace("-master", string.Empty);
        }
        else if (el.Name == ns + "availability")
        {
            prod.Availability = el.Value == "in stock";
        }
    }
}

筆記:

  • Descendants()在道德上是錯誤的。 /rss/channel/itemitem的固定位置,您非常清楚。 不是//item 因為明天可能有一個rss/foo/item ,所以今天不存在。 您嘗試編寫代碼,以使其與可以添加到xml的其他信息向前兼容。
  • 我討厭xml名稱空間...而且有多個嵌套名稱空間的xml。 我多么討厭那些。 但是比我聰明的人決定他們存在。 我接受。 我使用它們編寫代碼。 在LINQ-to-XML中,這非常容易。 有一個XNamespace甚至有一個重載的+運算符。

    請注意,如果您是微優化器(我盡量不要,但我必須承認,但是我的手有點發癢),則可以預先計算for循環內使用的各種ns + "xxx" ,因為目前尚不清楚,但每個周期都將對其進行重建。 XName的內部構建方式...哦,這很有趣,相信我。

     private static readonly XNamespace googleNs = "http://base.google.com/ns/1.0"; private static readonly XName idName = googleNs + "id"; private static readonly XName availabilityName = googleNs + "availability"; 

    接着

     if (el.Name == idName) { prod.SKU = el.Value.Replace("-master", string.Empty); } else if (el.Name == availabilityName) { prod.Availability = el.Value == "in stock"; } 

嘗試以下操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            new Item(FILENAME);

        }
    }
    public class Item
    {
        public static List<Item> items { get; set; }

        public string availability { get; set; }
        public string id { get; set; }

        public Item() { }
        public Item(string filename)
        {
            string xml = File.ReadAllText(filename);

            XDocument doc = XDocument.Parse(xml);
            XElement root = doc.Root;
            XNamespace ns = root.GetDefaultNamespace();

            Item.items = doc.Descendants(ns + "item").Select(x => new Item() {
                availability = (string)x.Element(ns + "availability"),
                id = (string)x.Element(ns + "id")
            }).ToList();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM