0

很抱歉这篇长篇文章......但我对这项任务感到头疼。

我有一个一英里长的 xml 文档,我需要在其中提取一个列表,使用不同的值,并传递给 web.xml 以进行转换。

我已经使用 xslt 和密钥完成了任务,但努力迫使服务器屈服。

描述:xml 中的数百个产品,都具有多个命名和标识的类别,所有类别都具有至少一个具有名称和标识的子类别。

类别在 ID 上是唯一的,所有子类别在该类别中都是唯一的:

大文件的简化示例(我们的大量信息与任务无关):

<?xml version="1.0" encoding="utf-8"?>
<root>
<productlist>
<product id="1">
<name>Some Product</name>
<categorylist>
<category id="1">
<name>cat1</name>
<subcategories>
<subcat id="1">
<name>subcat1</name>
</subcat>
<subcat id="2">
<name>subcat1</name>
</subcat>
</subcategories>
</category>
<category id="2">
<name>cat1</name>
<subcategories>
<subcat id="1">
<name>subcat1</name>
</subcat>
</subcategories>
</category>
<category id="3">
<name>cat1</name>
<subcategories>
<subcat id="1">
<name>subcat1</name>
</subcat>
</subcategories>
</category>
</categorylist>
</product>
<product id="2">
<name>Some Product</name>
<categorylist>
<category id="1">
<name>cat1</name>
<subcategories>
<subcat id="2">
<name>subcat2</name>
</subcat>
<subcat id="4">
<name>subcat4</name>
</subcat>
</subcategories>
</category>
<category id="2">
<name>cat2</name>
<subcategories>
<subcat id="1">
<name>subcat1</name>
</subcat>
</subcategories>
</category>
<category id="3">
<name>cat3</name>
<subcategories>
<subcat id="1">
<name>subcat1</name>
</subcat>
</subcategories>
</category>
</categorylist>
</product>
</productlist>
</root>

期望的结果:

<?xml version="1.0" encoding="utf-8"?>
<root>
<maincat id="1">
<name>cat1</name>
<subcat id="1"><name>subcat1</name></subcat>
<subcat id="2"><name>subcat2</name></subcat>
<subcat id="3"><name>subcat3</name></subcat>
</maincat>
<maincat id="2">
<name>cat2</name>
<subcat id="1"><name>differentsubcat1</name></subcat>
<subcat id="2"><name>differentsubcat2</name></subcat>
<subcat id="3"><name>differentsubcat3</name></subcat>
</maincat>
<maincat id="2">
<name>cat2</name>
<subcat id="1"><name>differentsubcat1</name></subcat>
<subcat id="2"><name>differentsubcat2</name></subcat>
<subcat id="3"><name>differentsubcat3</name></subcat>
</maincat>
</root>

(原来将从 2000 个产品中产生 10 个类别,其中包含 5 到 15 个子类别)

尝试的事情:

  1. Xslt with keys - 工作正常,但性能不佳
  2. 玩过linq:

           IEnumerable<XElement> mainCats =
                    from Category1 in doc.Descendants("product").Descendants("category") select Category1;
    
                var cDoc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement("root"));
                cDoc.Root.Add(mainCats);
                cachedCategoryDoc = cDoc.ToString();
    

    结果是“仅限类别”(不是类别或子类别的不同值)

对其应用相同的 xlst,并获得了相当好的性能......但仍远不能使用......

我可以对 linq 语句应用某种魔法来获得所需的输出吗?

一卡车的好业力会传给那些可以为我指明正确方向的人。

//斯蒂恩

笔记:

  • 如果有人有更好的选择,我不会坚持使用 linq/XDocument
  • 目前在 .net 3.5 上,如果需要可以切换到 4
4

3 回答 3

1

试试这个,我已经为它做了一些事情。缺少属性,您可以使用 XElement ctor 添加它们

 var doc = XDocument.Load(reader);
                    IEnumerable<XElement> mainCats =
                        doc.Descendants("product").Descendants("category").Select(r =>
                            new XElement("maincat", new XElement("name", r.Element("name").Value),
                                r.Descendants("subcat").Select(s => new XElement("subcat", new XElement("name", s.Element("name").Value)))));


                    var cDoc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement("root"));
                    cDoc.Root.Add(mainCats);
                    var cachedCategoryDoc = cDoc.ToString();

问候。

于 2012-05-25T12:40:41.617 回答
1

如果我正确理解了你的问题,这里有一个 LINQ 尝试。

下面的查询解析您的 XML 数据并创建一个自定义类型,该类型表示一个类别并包含该元素的子类别。

解析后,数据按类别 ID 分组,以获得每个类别的不同子类别。

var doc = XElement.Load("path to the file");
var results = doc.Descendants("category")
    .Select(cat => new
    {
        Id = cat.Attribute("id").Value,
        Name = cat.Descendants("name").First().Value,
        Subcategories = cat.Descendants("subcat")
            .Select(subcat => new
            {
                Id = subcat.Attribute("id").Value,
                Name = subcat.Descendants("name").First().Value
            })
     })
     .GroupBy(x=>x.Id)
     .Select(g=>new
     {
         Id = g.Key,
         Name = g.First().Name,
         Subcategories = g.SelectMany(x=>x.Subcategories).Distinct()
     });

根据上面的结果,您可以使用以下代码创建文档:

var cdoc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement("root")); 
cdoc.Root.Add(
    results.Select(x=>
    {
        var element = new XElement("maincat", new XAttribute("id", x.Id));
        element.Add(new XElement("name", x.Name));
        element.Add(x.Subcategories.Select(c=>
        {
            var subcat = new XElement("subcat", new XAttribute("id", c.Id));
            subcat.Add(new XElement("name", c.Name));
            return subcat;
        }).ToArray());
        return element;
    }));
于 2012-05-25T12:42:58.183 回答
1

这会将您的 xml 解析为具有所有不同子类别名称的类别字典。它使用来自这个库的 XPath:https ://github.com/ChuckSavage/XmlLib/

XElement root = XElement.Load(file);
string[] cats = root.XGet("//category/name", string.Empty).Distinct().ToArray();
Dictionary<string, string[]> dict = new Dictionary<string, string[]>();
foreach (string cat in cats)
{
    // Get all the categories by name and their subcat names
    string[] subs = root
        .XGet("//category[name={0}]/subcategories/subcat/name", string.Empty, cat)
        .Distinct().ToArray();
    dict.Add(cat, subs);
}

或解析为一个语句:

Dictionary<string, string[]> dict = root
    .XGet("//category/name", string.Empty)
    .Distinct()
    .ToDictionary(cat => cat, cat => root
        .XGet("//category[name={0}]/subcategories/subcat/name", string.Empty, cat)
        .Distinct().ToArray());

我给你从字典中组装生成的 xml 的任务。

于 2012-06-05T11:26:54.367 回答