如何将具有相同名称和相同属性名称的节点添加到集合中?

问题描述 投票:0回答:1

我有xml文件看起来像这样

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="101">3.1256
    <auth-name>Idris Polk</auth-name>
    <auth id="a1">The author is a Professor of Physics at MIT</auth>
    <ph ll="p1">336451234</ph> <ph ll="p2">336051294</ph> <mail>[email protected]</mail> <ph ll="p3">336133291</ph>
    </book>
    <book id="105">4.2250
    <auth-name>Andre Olo</auth-name>
    <auth id="a2">The research fellow at NSF</auth>
    <ph ll="p101">336200316</ph>, <ph ll="p102">336151093</ph>, <ph ll="p103">336151094</ph>, <mail>[email protected]</mail> <ph ll="p111">336900336</ph>, <ph ll="p112">336154094</ph>, <ph ll="p113">336151098</ph>, <mail>[email protected]</mail>
    </book>
    <ebook id="1">4.2350
    <auth-name>John Bart</auth-name>
    <auth id="ae1">The research fellow at Caltech</auth>
    <ph ll="p50">336200313</ph>, <ph ll="p51">336151090</ph>, <ph ll="p52">336851091</ph>, <ph ll="p53">336151097</ph>, <mail>[email protected]</mail> <ph ll="p111">336000311</ph>, <ph ll="p112">336224094</ph>
    </ebook>
...
</books>

当有超过2个节点ph由空格分隔或用逗号和空格分隔时,如何将具有特定父节点的属性ll的节点ph获取到集合?如果任何其他字符/节点(或任何类型的字符串)落在一个ph节点和下一个ph节点之间,则不会在集合中进行。 e.x.如果<book id="...">节点包含时尚ph中的<ph ll="1">...</ph> <ph ll="2">...</ph> <mail>...<mail> <ph ll="3">...</ph>节点,那么它将不会被添加到集合中,但是如果它们是<ph ll="1">...</ph> <ph ll="2">...</ph> <ph ll="3">...</ph> <mail>...<mail>的顺序,那么<ph ll="1">...</ph> <ph ll="2">...</ph> <ph ll="3">...</ph>应该作为单个元素添加到集合中,因为有超过2个ph节点仅由给定父节点中的空格分隔..

显然很简单

var cls=doc.Descendants("ph")
                .Where(Attribute("ll"));

不会这样做。有人可以帮忙吗?

c# linq-to-xml
1个回答
1
投票

请尝试以下代码。我使用了xml linq和一个帮助方法。 :

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

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

            var books = doc.Descendants("books").Elements().Select(x => new { book = x, sequence = TestChildren(x) }).Where(x => x.sequence != null).ToList();

            string results = string.Join("\n", books.SelectMany(x => x.sequence).Select((x, i) => (i + 1).ToString() + ") " + string.Join("", x.Select(y => y.ToString()))));

            Console.WriteLine(results);
            Console.ReadLine();

        }
        static List<List<XElement>> TestChildren(XElement book)
        {
            List<List<XElement>> results = null;
            List<XElement> children = book.Elements().ToList();
            // get lls, make -1 if not ph
            List<int> lls = children.Select(x => x.Name.LocalName != "ph" ? -1 : int.Parse(((string)x.Attribute("ll")).Substring(1))).ToList();
            //check for 3 in a row incrementing
            int startIndex = -1;
            int numberInSequence = 0;
            for (int i = 0; i < lls.Count() - 3; i++)
            {
                //test for 3 in a row
                if ((lls[i] + 1 == lls[i + 1]) && (lls[i] + 2 == lls[i + 2]))
                {
                    //if first sequency found set start index and lenght to 3
                    if (startIndex == -1)
                    {
                        startIndex = i;
                        numberInSequence = 3;
                    }
                    else
                    {
                        //increase length if more than 3
                        numberInSequence++;
                    }

                }
                else
                {
                    //if a sequence has been found add to results
                    if (numberInSequence >= 3)
                    {
                        List<XElement> sequence = new List<XElement>(children.Skip(startIndex).Take(numberInSequence).ToList());
                        if (results == null) results = new List<List<XElement>>();
                        results.Add(sequence);
                        startIndex = -1;
                        numberInSequence = 0;
                    }
                }
            }
            if (numberInSequence >= 3)
            {
                List<XElement> sequence = new List<XElement>(children.Skip(startIndex).Take(numberInSequence).ToList());
                if (results == null) results = new List<List<XElement>>();
                results.Add(sequence);
            }
            return results;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.