XML для LINQ, как получить точную информацию?

1

Я хочу извлечь некоторую информацию из примера xml ниже. Я хочу вытащить коллекцию строк, которые содержат интересующую меня колонку.

Я не знаю, как это сделать... Я пробовал этот код, но он не работал:

    XElement elem = XElement.Load("SIMC.xml");
    var homePhone = from phoneno in elem.Elements("row")
                    where (string)phoneno.Element("col").Attribute("name") == "NAZWA"
                    select phoneno;
   // Console.WriteLine("List HomePhone Nos.");
    foreach (XElement xEle in homePhone)
    {
        MessageBox.Show(xEle.Element("col").Value);
    }

Вот пример XML, который я пытаюсь проанализировать:

<?xml version="1.0" encoding="UTF-8"?>
<teryt>
<catalog name="SIMC" type="all" date="2015-01-01">
<row>
<col name="WOJ">18</col>
<col name="POW">16</col>
<col name="GMI">13</col>
<col name="RODZ_GMI">2</col>
<col name="RM">00</col>
<col name="MZ">1</col>
<col name="NAZWA">Na Polu</col>
<col name="SYM">0664326</col>
<col name="SYMPOD">0664310</col>
<col name="STAN_NA">2015-01-01</col>
</row>
<row>
<col name="WOJ">28</col>
<col name="POW">06</col>
<col name="GMI">05</col>
<col name="RODZ_GMI">2</col>
<col name="RM">03</col>
<col name="MZ">1</col>
<col name="NAZWA">Majerka</col>
<col name="SYM">0761615</col>
<col name="SYMPOD">0761609</col>
<col name="STAN_NA">2015-01-01</col>
</row>
<row>
<col name="WOJ">12</col>
<col name="POW">09</col>
<col name="GMI">03</col>
<col name="RODZ_GMI">5</col>
<col name="RM">00</col>
<col name="MZ">1</col>
<col name="NAZWA">Pod Kamiennikiem</col>
<col name="SYM">0328485</col>
<col name="SYMPOD">0328456</col>
<col name="STAN_NA">2015-01-01</col>
</row>
<row>
<col name="WOJ">32</col>
<col name="POW">17</col>
<col name="GMI">04</col>
<col name="RODZ_GMI">5</col>
<col name="RM">01</col>
<col name="MZ">1</col>
<col name="NAZWA">Miłogoszcz</col>
<col name="SYM">0530732</col>
<col name="SYMPOD">0530732</col>
<col name="STAN_NA">2015-01-01</col>
</row>

Я хочу извлечь элементы строки, где есть столбец с name атрибута, равным NAZWA и значением столбца Miłogoszcz.

Мой код пока ничего не показывает

  • 0
    Пожалуйста, не используйте ссылки на внешние источники для поддержки вашего вопроса. Они могут (и часто так) устаревают или просто пропадают, что делает сам вопрос бесполезным для будущих читателей. Пожалуйста, предоставьте краткий пример формата XML в вашем вопросе, чтобы вопрос был полностью автономным. Также, пожалуйста, будьте более конкретны, чем «это не сработало». Четко объясните, что сделал код, который вы пробовали, и чем он отличается от того, что вы ожидали или хотели.
Теги:
linq

2 ответа

0
Лучший ответ

Если мы думаем об этой проблеме интуитивно, что мы действительно хотим, так это:

Верните строки, где есть столбец в этой строке, который имеет атрибут "имя" с определенным значением и значением столбца с определенным значением.

Предположим, что у нас уже есть IEnumerable<XElement> rows которые представляют элементы строки XML файла. Затем мы могли выбрать только те строки, которые нам нужны, используя методы расширения LINQ. Здесь может выглядеть одна такая функция.

    public static IEnumerable<XElement> GetRowsWithColumn(IEnumerable<XElement> rows, String name, String value) 
    {
        return rows
            .Where(row => row.Elements("col") //Get Columns
                .Any(col => //This column should...
                    col.Attributes("name").Any(attr => attr.Value.Equals(name)) //have the right name attribute
                    && col.Value.Equals(value))); //and have the right value
    }

Вот полная программа, которая, я считаю, делает то, что вы просите. Он открывает файл и затем исследует элементы, возвращая строки, где есть подэлемент "col", который имеет имя атрибута со значением NAZWA и этот столбец имеет значение Miłogoszcz

Этот код использует функцию, которую мы написали выше, чтобы вы могли подключить все, что хотите, для атрибута имени столбца и значения столбца.

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

namespace StackOverflowTest
{
    class Program
    {
        public static IEnumerable<XElement> GetRowsWithColumn(IEnumerable<XElement> rows, String name, String value) 
        {
            return rows
                .Where(row => row.Elements("col")
                    .Any(col =>
                        col.Attributes("name").Any(attr => attr.Value.Equals(name))
                        && col.Value.Equals(value)));
        }
        static void Main(string[] args)
        {
            //Load file
            XElement elem = XElement.Load("./test.xml");

            //Get Rows
            var rows = elem
                .Elements("catalog")
                .Elements("row");

            //Filter rows
            var interestingRows = GetRowsWithColumn(rows, "NAZWA", "Miłogoszcz");

            //Print rows
            foreach (var row in interestingRows)
            {
                //This is MessageBox.Show in your example
                Console.WriteLine(row);
            }

            Console.Read();
        }
    }
}

Надеюсь, это решит вашу проблему. Дай мне знать, если я пропустил что-нибудь.

Обратите внимание, что я действительно изменил ваш XML файл, чтобы быть допустимым, включив блоки закрытия для элементов верхнего уровня

<?xml version="1.0" encoding="UTF-8"?>
<teryt>
<catalog name="SIMC" type="all" date="2015-01-01">
<row>
<col name="WOJ">18</col>
<col name="POW">16</col>
<col name="GMI">13</col>
<col name="RODZ_GMI">2</col>
<col name="RM">00</col>
<col name="MZ">1</col>
<col name="NAZWA">Na Polu</col>
<col name="SYM">0664326</col>
<col name="SYMPOD">0664310</col>
<col name="STAN_NA">2015-01-01</col>
</row>
<row>
<col name="WOJ">28</col>
<col name="POW">06</col>
<col name="GMI">05</col>
<col name="RODZ_GMI">2</col>
<col name="RM">03</col>
<col name="MZ">1</col>
<col name="NAZWA">Majerka</col>
<col name="SYM">0761615</col>
<col name="SYMPOD">0761609</col>
<col name="STAN_NA">2015-01-01</col>
</row>
<row>
<col name="WOJ">12</col>
<col name="POW">09</col>
<col name="GMI">03</col>
<col name="RODZ_GMI">5</col>
<col name="RM">00</col>
<col name="MZ">1</col>
<col name="NAZWA">Pod Kamiennikiem</col>
<col name="SYM">0328485</col>
<col name="SYMPOD">0328456</col>
<col name="STAN_NA">2015-01-01</col>
</row>
<row>
<col name="WOJ">32</col>
<col name="POW">17</col>
<col name="GMI">04</col>
<col name="RODZ_GMI">5</col>
<col name="RM">01</col>
<col name="MZ">1</col>
<col name="NAZWA">Miłogoszcz</col>
<col name="SYM">0530732</col>
<col name="SYMPOD">0530732</col>
<col name="STAN_NA">2015-01-01</col>
</row>
</catalog>
</teryt>
1

Вам нужно либо использовать Descendents либо правильно следовать иерархии XML, вы пропускаете два уровня в своей логике. Я также изменил (string) на .Value чтобы работать правильно.

XElement elem = XElement.Load("SIMC.xml");
var homePhone = from phoneno in elem.Elements("teryt")
                                    .Elements("catalog")
                                    .Elements("row")
                where phoneno.Elements("col")
                             .Any(xelm =>
                                      xelm.Attribute("name").Value == "NAZWA" &&
                                      xelm.Value == "Miłogoszcz")
                select phoneno;
// Console.WriteLine("List HomePhone Nos.");
foreach (XElement xEle in homePhone)
{
    //Note that you need to decide how to format this
    MessageBox.Show(string.Join(", ",
                    xEle.Select(x => x.Attribute("name").Value + "=" + x.Value));
}
  • 0
    И где я должен разместить точное название, например "На Полу", чтобы получить информацию о строке, содержащей "На Полу"? Спасибо за помощь ;)
  • 0
    @PiotrBagier: Обновлено, обратите внимание, что «отображение всей строки» - это еще одна проблема, поскольку вы не указали, как вы хотели, чтобы она выглядела, поэтому я просто вывел исходную <row> на данный момент.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню