Как найти строку в хмл файле

I would like to know how to find a string in XML file.

Say this is the XML file i have (these are the SQL server instances btw, irrelevant)

<?xml version="1.0" encoding="utf-8" ?>
<Servernames>
    <loc country="Lockheed">
        <Servername>instance1server1</Servername>
        <Servername>instance2server2</Servername>
        <Servername>10.90</Servername>
    </loc>
    <loc country="SouthAmerica">
        <Servername>Hide your heart</Servername>
        <Servername>Bonnie Tyler</Servername>
        <Servername>10.0</Servername>
    </loc>
    <loc country="Britian">
        <Servername>GreatestHits</Servername>
        <Servername>DollyParton</Servername>
        <Servername>thisis</Servername>
    </loc>
</Servernames>

So what happens is i get a string from the user in any format say for example i only get instance and then i want the listbox to display all the servernames that start with server in the above case it will be

instance1server1
instance2serve2

and so on..
Not sure how to achieve this, do i have to open stream reader or just get a string and browser thru the xml file?

UPDATED

private void button1_Click(object sender, RoutedEventArgs e)
{
    textBox1.Clear();
    string fileName = "c:\users\xxxx\documents\visual studio 2010\Projects\WpfApplication2\WpfApplication2\XML.xml";

        var doc = XDocument.Load(fileName);
        var findString = "Server";

        var results = doc.Element("Servernames").Descendants("Servername").Where(d => d.Value.Contains(findString)).Select(d => d.Value);
        listBox1.Items.Add(results.ToString());
        textBox1.Text = results.ToString();
}

i am simply getting this in the text box :System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.Xml.Linq.XElement,System.String]

enter image description here

strong textUPDATE2

.cs file code

private void button1_Click(object sender, RoutedEventArgs e)
{
textBox1.Clear();

        string fileName = "c:\users\xxxxx\documents\visual studio 2010\Projects\WpfApplication2\WpfApplication2\XML.xml";

        var doc = XDocument.Load(fileName);
        var findString = "Server";

        var results = doc.Element("Servernames").Descendants("Servername").Where(d => d.Value.Contains(findString)).Select(d => d.Value);

        Servers = new ObservableCollection<string>(results);

        MessageBox.Show("THis is loaded");

    }

XAML looks like this

<ListBox   Height="200" HorizontalAlignment="Left" Margin="200,44,0,0" x:Name="ListBox1" VerticalAlignment="Top" Width="237">

enter image description here

Я хотел бы знать, как найти строку в файле XML.

Скажи, что это XML-файл, который у меня есть (это экземпляры SQL-сервера, кстати, не имеет значения)

<?xml version="1.0" encoding="utf-8" ?>
<Servernames>
    <loc country="Lockheed">
        <Servername>instance1server1</Servername>
        <Servername>instance2server2</Servername>
        <Servername>10.90</Servername>
    </loc>
    <loc country="SouthAmerica">
        <Servername>Hide your heart</Servername>
        <Servername>Bonnie Tyler</Servername>
        <Servername>10.0</Servername>
    </loc>
    <loc country="Britian">
        <Servername>GreatestHits</Servername>
        <Servername>DollyParton</Servername>
        <Servername>thisis</Servername>
    </loc>
</Servernames>

Итак, что происходит, я получаю строку от пользователя в любом формате, скажем, например, я получаю только экземпляр, а затем я хочу, чтобы в списке отображались все имена серверов, начинающиеся с сервера, в приведенном выше случае это будет

instance1 сервер1
instance2 serve2

и так далее. Не знаете, как этого добиться, нужно ли открывать потоковый ридер или просто получить строку и браузер через файл xml?

ОБНОВЛЕНО

private void button1_Click(object sender, RoutedEventArgs e)
{
    textBox1.Clear();
    string fileName = "c:\users\xxxx\documents\visual studio 2010\Projects\WpfApplication2\WpfApplication2\XML.xml";

        var doc = XDocument.Load(fileName);
        var findString = "Server";

        var results = doc.Element("Servernames").Descendants("Servername").Where(d => d.Value.Contains(findString)).Select(d => d.Value);
        listBox1.Items.Add(results.ToString());
        textBox1.Text = results.ToString();
}

я просто получаю это в текстовом поле:System.Linq.Enumerable + WhereSelectEnumerableIterator`2 [System.Xml.Linq.XElement, System.String]

сильный текст ОБНОВЛЕНИЕ2

Код файла.cs

private void button1_Click(отправитель объекта, RoutedEventArgs e) {textBox1.Clear ();

        string fileName = "c:\users\xxxxx\documents\visual studio 2010\Projects\WpfApplication2\WpfApplication2\XML.xml";

        var doc = XDocument.Load(fileName);
        var findString = "Server";

        var results = doc.Element("Servernames").Descendants("Servername").Where(d => d.Value.Contains(findString)).Select(d => d.Value);

        Servers = new ObservableCollection<string>(results);

        MessageBox.Show("THis is loaded");

    }

XAML выглядит так

<ListBox   Height="200" HorizontalAlignment="Left" Margin="200,44,0,0" x:Name="ListBox1" VerticalAlignment="Top" Width="237">

Здравствуйте. Ситуация: есть модель(дисериализованный файл), довольно большая. В ней много строк и вложенных объектов. (Модель YML каталога).

[XmlRoot("yml_catalog")]
public class YMLCatalog
{
    /// <summary>
    /// Дата и время генерации YML файла на стороне магазина
    /// </summary>
    [Required]
    [XmlAttribute("date")]
    public string Date { get; set; }

    /// <summary>
    /// Магазин
    /// </summary>
    [Required]
    [ValidateObject]
    [XmlElement(ElementName = "shop")]
    public Shop Shop { get; set; }
}

/// <summary>
/// Точка продаж
/// https://yandex.ru/support/webmaster/goods-prices/technical-requirements.html
/// </summary>
public class Shop
{
    /// <summary>
    /// Название магазина.
    /// </summary>
    [Required]
    [XmlElement("name")]
    public string Name { get; set; }

    /// <summary>
    /// Название компании
    /// </summary>
    [Required]
    [XmlElement("company")]
    public string Company { get; set; }
    ... и тд.
}

При валидации модели, в случае ошибки, я получаю (при помощи магии. См. краткое описание в комментариях) путь к ошибке. Например для YML файла с ошибкой в теге price, 0го оффера, в виде отсутствия цены, я получаю путь: shop/offers/offer[‘0 или 1’, смотря как удобнее. Для XPath лучше 1]/price Value: Текст ошибки. (Value – поле со значением тега, аналогично может быть для атрибутов)

Нас интересует: shop/offers/offer[0]/price

По этому пути, мне нужно определить номер строки, где находиться этот тег. Чтобы указать пользователю где ошибка.

Что я пробовал:

1) Сделал через регулярные выражения. Сначала последовательно нахожу индекс элементов по пути, как получу индекс начала тега Price в файле. Затем собираю список строк в файле и нахожу номер строки для вывода, относительно всего файла. – Это работает, но меня не устраивает. Слишком медленно, а у меня могут быть очень большие файлы

2) Попробовал сделать через XPath. Т.е например можно легко получить элемент тега вот так:

XmlDocument document = new XmlDocument();
document.LoadXml(text);
var node = document.SelectSingleNode("//shop/offers/offer[1]/price");// это для примера

3) Есть вариант с созданием своего дессериализатора + атрибутов валидации для него, чтобы к каждому полю в модели приписывать в метаданных IXmlLineInfo – который в стандартном XmlSerializer к сожалению используется только при выдаче информации об ошибке – но это долго, а те готовые, что я нашел, не поддерживаются в net core… UPD: также в таком случае требуется поддержка не только составных объектов, но и простых + простых атрибутов (string, int, long и тп)

Вопрос 1: XPath как-нибудь позволяет получить кол-во элементов выше (или лучше их список) ? Вроде комбинировать preceding и ancestor нельзя (ссылка) – Но опять же, даже если это получиться, придется искать индекс, создавая список строк файла. – Не очень хорошо, хотелось бы узнать номер строки ошибки другим способом

Пробовал “//shop/offers/offer[ 1 ]/price/preceding::*”, но в таком случае игнорируются все элементы выше shop, почему не знаю. (когда использовал count(…), получал 27 элементов) – Думаю это всяко лучше только регулярных выражений

Знаете еще способ? Прошу в ответы:)

Главный вопрос: Так как лучше всего найти номер строки ошибки, имея XML и путь к тегу?

P.S Производительность решения приветствуется)

От:

ra88

 
Дата:  24.09.10 06:56
Оценка:

Доброго рабочего дня!

собственно имеется XML фаил, который считывается по средством XmlDocument.Load(filename)

Затем я бегаю по дереву с помощю SelectNodes() и ChildNodes. В определённый момент хочется узнать на какой строке в файле находится открывающий тэг выбранного XmlNode.

Как это сделать?

while true;


Re: номер строки в XML файле

От:

Arnx

Россия

 
Дата:  24.09.10 07:00
Оценка:

R>собственно имеется XML фаил, который считывается по средством XmlDocument.Load(filename)
R>Затем я бегаю по дереву с помощю SelectNodes() и ChildNodes. В определённый момент хочется узнать на какой строке в файле находится открывающий тэг выбранного XmlNode.
R>Как это сделать?
Вообще-то говоря, строк как таковых в хмл документе нету. Если хочется знать “как бы представление” то можешь держать текущую глубину элемента = собственно все пройденные узлы *(или как будешь справляться с закрывающими тегами) + дети.
Может тебе проще параллельно загнать построчно в хэш таблицу и вытаскивать оттуда по какому-либо ключу?


Re: номер строки в XML файле

От:

HowardLovekraft

 
Дата:  24.09.10 07:03
Оценка:

Здравствуйте, ra88, Вы писали:

R>В определённый момент хочется узнать на какой строке в файле находится открывающий тэг выбранного XmlNode.

А если XML хранится в файле в одну строку:

<root><child>123</child></root>

?


Re[2]: номер строки в XML файле

От:

ra88

 
Дата:  24.09.10 07:07
Оценка:

Здравствуйте, HowardLovekraft, Вы писали:

HL>Здравствуйте, ra88, Вы писали:


R>>В определённый момент хочется узнать на какой строке в файле находится открывающий тэг выбранного XmlNode.

HL>А если XML хранится в файле в одну строку:
HL>

HL><root><child>123</child></root>


HL>?

тогда номер строки 1.

while true;


Re: номер строки в XML файле

От:

Closer

 
Дата:  24.09.10 07:09
Оценка:

20 (4)

Здравствуйте, ra88, Вы писали:

[skipped]

R>Как это сделать?

Для начала научится пользоваться поиском.

Здесь

Автор: Closer
Дата: 17.10.06

решение.

Мы были здесь. Но пора идти дальше. (с) Дуглас Коупленд, Рабы “Микрософт”


Re[2]: номер строки в XML файле

От:

ra88

 
Дата:  24.09.10 07:15
Оценка:

Здравствуйте, Closer, Вы писали:

C>Здравствуйте, ra88, Вы писали:


C>[skipped]


R>>Как это сделать?


C>Для начала научится пользоваться поиском. Здесь

Автор: Closer
Дата: 17.10.06

решение.

while true;


Re: номер строки в XML файле

От:

_FRED_

Черногория

@ViIvanov
Дата:  24.09.10 10:30
Оценка:

8 (3)

Здравствуйте, ra88, Вы писали:

R>собственно имеется XML фаил, который считывается по средством XmlDocument.Load(filename)

R>Затем я бегаю по дереву с помощю SelectNodes() и ChildNodes. В определённый момент хочется узнать на какой строке в файле находится открывающий тэг выбранного XmlNode.
R>Как это сделать?

А использовать современное API (System.Xml.Linq) для работы с xml возможность есть? В нём уже каждый объект реализует System.Xml.IXmlLineInfo.

Help will always be given at Hogwarts to those who ask for it.


Re[2]: номер строки в XML файле

От:

ra88

 
Дата:  24.09.10 11:35
Оценка:

Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, ra88, Вы писали:


R>>собственно имеется XML фаил, который считывается по средством XmlDocument.Load(filename)

R>>Затем я бегаю по дереву с помощю SelectNodes() и ChildNodes. В определённый момент хочется узнать на какой строке в файле находится открывающий тэг выбранного XmlNode.
R>>Как это сделать?

_FR>А использовать современное API (System.Xml.Linq) для работы с xml возможность есть? В нём уже каждый объект реализует System.Xml.IXmlLineInfo.

пока нет. надо исходить из того, что имеется только .NET 2.0
Но спасибо за информацию. В будущем пригодится.

while true;

Подождите ...

Wait...

  • Переместить
  • Удалить
  • Выделить ветку

Пока на собственное сообщение не было ответов, его можно удалить.

Добавить комментарий