代码之家  ›  专栏  ›  技术社区  ›  Don_B

如何将具有相同名称和相同属性名称的节点获取到集合?

  •  0
  • Don_B  · 技术社区  · 7 年前

    我有这样的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>IP.00@yandex.com</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>An.olo@yandex.com</mail> <ph ll="p111">336900336</ph>, <ph ll="p112">336154094</ph>, <ph ll="p113">336151098</ph>, <mail>ano_ano@yandex.com</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>bart.j@yandex.com</mail> <ph ll="p111">336000311</ph>, <ph ll="p112">336224094</ph>
        </ebook>
    ...
    </books>
    

    如何获取节点 ph 带属性 ll 当有两个以上的节点时,集合的特定父节点的 酸碱度 哪些是用空格分隔的,哪些是用逗号和空格分隔的?如果任何其他字符/节点(或任何类型的字符串)介于 酸碱度 节点和下一个 酸碱度 节点,则不会在集合中获取该节点。e、 x.如果a <book id="..."> 节点包含 酸碱度 时尚中的节点 <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个以上 酸碱度 在给定父节点中,节点仅由空格分隔。。

    显然是一个简单的

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

    不行。有人能帮忙吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   jdweng    7 年前

    请尝试下面的代码。我使用了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;
            }
        }
    }