Как фильтровать узлы XML и его дочерние узлы в документе XML? - PullRequest
1 голос
/ 03 октября 2019

Итак, у меня есть XML-документ, в котором я получаю HttpWebResponse от API, с которым я работаю. Тем не менее, документ, в котором я получаю, имеет длину около 166 тысяч строк и содержит много ненужных данных, в которых я не нуждаюсь. Я прочитал документацию по API, и не похоже, что есть атрибут фильтрации, который соответствует моим потребностям. Поэтому я решил, что отфильтрую это программно, но не смог добиться успеха в этой части. Итак, документ XML выглядит примерно так:

<sensortree>
        <nodes>
            <group id="">
                <name></name>
                <id></id>
                <url></url>
                <tags></tags>
                <priority></priority>
                <fixed></fixed>
                <hascomment></hascomment>
                <status_raw></status_raw>
                <active></active>
                <probenode id="">
                    <name></name>
                    <id></id>
                    <url></url>
                    <tags></tags>
                    <priority></priority>
                    <fixed></fixed>
                    <hascomment></hascomment>
                    <status_raw></status_raw>
                    <active></active>
                    <group id="">
                        <name></name>
                        <id></id>
                        <url></url>
                        <tags></tags>
                        <priority></priority>
                        <fixed></fixed>
                        <hascomment></hascomment>
                        <status_raw></status_raw>
                        <active></active>
                        <group id="">
                            <name></name>
                            <id></id>
                            <url></url>
                            <tags></tags>
                            <priority></priority>
                            <fixed></fixed>
                            <hascomment></hascomment>
                            <status_raw></status_raw>
                            <active></active>
                            <group id="">
                                <name></name>
                                <id></id>
                                <url></url>
                                <tags></tags>
                                <priority></priority>
                                <fixed></fixed>
                                <hascomment></hascomment>
                                <status_raw></status_raw>
                                <active></active>
                                <device id="">
                                    <summary></summary>
                                    <name></name>
                                    <deviceicon></deviceicon>
                                    <id></id>
                                    <url></url>
                                    <tags></tags>
                                    <priority></priority>
                                    <fixed></fixed>
                                    <hascomment></hascomment>
                                    <host></host>
                                    <status_raw></status_raw>
                                    <active></active>
                                    <sensor id="">
                                        <name></name>
                                        <id></id>
                                        <url></url>
                                        <tags></tags>
                                        <priority></priority>
                                        <fixed></fixed>
                                        <hascomment></hascomment>
                                        <sensortype></sensortype>
                                        <sensorkind></sensorkind>
                                        <interval></interval>
                                        <status_raw></status_raw>
                                        <status></status>
                                        <datamode></datamode>
                                        <lastvalue></lastvalue>
                                        <lastvalue_raw></lastvalue_raw>
                                        <statusmessage></statusmessage>
                                        <active></active>
                                    </sensor>
                                </device>
                            </group>
                        </group>
                    </group>
                </probenode>
            </group>
        </nodes>
</sensortree>

Теперь вы можете заметить, что все элементы пусты, потому что я удалил все внутренние тексты элементов, так как не могу поделиться этой информацией с общедоступнойХотя я уверяю вас, что все элементы имеют внутренние тексты в реальности. Теперь у каждого устройства есть несколько датчиков, но все они выглядят одинаково, поэтому я включил только один. Все элементы группы также имеют различную структуру дочерних узлов, поэтому каждая группа не похожа на другую. Теперь мне нужны только элементы «узлы», «группа», «пробенод», «устройство», «датчик», «имя» и «id». Остальные элементы должны быть удалены из документа, в то время как я все еще сохраняю иерархическую структуру документа. Короче говоря, я хочу выполнить цикл по всем узлам и дочерним узлам каждого узла, посмотреть, является ли элемент элементом, который я хочу сохранить, и удалить его, если это не так. Другой поворот заключается в том, что я не знаю, является ли XPath вариантом, потому что структура не везде одинакова. Вот что я попробовал:

//Method 1 - It doesn't delete the nodes that are not specified, I think it's because it doesn't check the childnodes because it does delete other nodes.
foreach (XmlNode node in xDoc)
            {
                if (node.Name == "group" || node.Name == "probenode" ||     node.Name == "device" || node.Name == "sensor")
                {
                }
                else
                {
                    node.ParentNode.RemoveChild(node);
                }
            }

//Method 2 - Not sure how to delete a node from a XmlReader instance 
StringWriter sw = new StringWriter();
            XmlTextWriter xw = new XmlTextWriter(sw);
            xDoc.WriteTo(xw);
            String xmlString = sw.ToString();

            XmlReader rdr = XmlReader.Create(new System.IO.StringReader(xmlString));
            while (rdr.Read())
            {
                if (rdr.NodeType == XmlNodeType.Element)
                {
                    if (rdr.LocalName == "group" || rdr.LocalName == "probenode" || rdr.LocalName == "device" || rdr.LocalName == "sensor"
                    || rdr.LocalName == "name" || rdr.LocalName == "lastvalue" || rdr.LocalName == "status")
                    {

                    }
                    else
                    {

                    }
                }
            }

Теперь я хочу, чтобы мой XML-документ выглядел после форматирования:

<sensortree>
        <nodes>
            <group id="">
                <name></name>
                <id></id>
                    <probenode id="">
                    <name></name>
                    <id></id>
                    <group id="">
                        <name></name>
                        <id></id>
                            <name></name>
                            <id></id>
                            <group id="">
                                <name></name>
                                <id></id>
                                <device id="">
                                    <name></name>
                                    <id></id>
                                    <sensor id="">
                                        <name></name>
                                        <id></id>
                                    </sensor>
                                </device>
                            </group>
                        </group>
                    </group>
                </probenode>
            </group>
        </nodes>
</sensortree>

Ответы [ 2 ]

2 голосов
/ 03 октября 2019

Использование System.Xml.Linq:

// first get System.Xml.Linq.XDocument from XmlDocument
var xDoc = XDocument.Parse(xmlDocument.OuterXml);

// remove elements from xDoc that do not match one of your expected tags
var tags = new string[] { "group", "sensor", ... }
xDoc.Root.Descendants().Where(d => !tags.Contains(d.Name.LocalName)).Remove();
0 голосов
/ 03 октября 2019

Проверьте, работает ли следующий рекурсивный алгоритм:

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 oldDoc = XDocument.Load(FILENAME);
            XElement oldNodes = oldDoc.Descendants("nodes").FirstOrDefault();

            string header = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><sensortree><nodes></nodes></sensortree>";

            XDocument newDoc = XDocument.Parse(header);
            XElement newNodes = newDoc.Descendants("nodes").FirstOrDefault();

            GetTreeRecursively(oldNodes, newNodes);

        }
        static void GetTreeRecursively(XElement oldElement, XElement newElement)
        {
            string[] findTags = { "group", "probenode", "device", "sensor" };

            List<XElement> oldChildren = oldElement.Elements().Where(x => findTags.Contains(x.Name.LocalName)).ToList();

            foreach (XElement oldChild in oldChildren)
            {
                XElement newChild = new XElement(oldChild.Name.LocalName, new XAttribute("id", (string)oldChild.Attribute("id")));
                newChild.Add(oldChild.Element("name"));
                newChild.Add(oldChild.Element("id"));
                newElement.Add(newChild);
                GetTreeRecursively(oldChild, newChild);
            }
        }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...