Прочитать следующее значение в файле XML

У меня есть такой XML-файл:

    <key>businessAddress</key>
    <string>Moka</string>
    <key>businessName</key>
    <string>Moka address</string>
    <key>Id</key>
    <string>39</string>
    <key>Cat</key>
    <string>216</string>
    <key>deals</key>

Я хочу прочитать следующее <string> значение, если ключ является идентификатором

Итак, что я сделал, это:

XmlTextReader reader = new XmlTextReader(file);

while (reader.Read())
{
    if (reader.Value.Equals("Id"))
    {
        reader.MoveToNextAttribute
    }  
}

но мне не удалось.

Спасибо за помощь

3 ответа

Решение

Вы можете использовать логический флаг, чтобы указать, следует ли читать значение следующего элемента:

bool shouldReadId = false;
while (reader.Read())
{
    if (reader.NodeType == XmlNodeType.Text && shouldReadId)
    {
        Console.WriteLine(reader.Value); // will print 39
        shouldReadId = false;
    }

    if (reader.Value.Equals("Id"))
    {
        // indicate that we should read the value of the next element
        // in the next iteration
        shouldReadId = true;
    }
}

Я хотел бы отметить, что XmlTextReader в основном заменен XmlReader:

Начиная с.NET Framework 2.0, мы рекомендуем вместо этого использовать класс System.Xml.XmlReader.

Хотя их объектная модель ничем не отличается.

Итак, если вы хотите использовать XmlTextReader, вы можете сделать что-то вроде:

public static class XmlReaderExtensions
{
    public static void EnsureRead(this XmlTextReader reader)
    {
        var isRead = reader.Read();
        if (!isRead)
            throw new InvalidOperationException("Failed to read");
    }

    public static void SkipUntil(this XmlTextReader reader, Func<XmlTextReader, Boolean> isStop)
    {
        while (!isStop(reader))
        {
            reader.EnsureRead();
        }
    }
}

...

var xml = @"<root>   <key>businessAddress</key>
    <string>Moka</string>
    <key>businessName</key>
    <string>Moka address</string>
    <key>Id</key>
    <string>39</string>
    <key>Cat</key>
    <string>216</string>
    <key>deals</key> </root>";

using (var stream = new MemoryStream(Encoding.Default.GetBytes(xml)))
using (var reader = new XmlTextReader(stream))
{
    reader.SkipUntil(cur => cur.Value == "Id");
    reader.EnsureRead(); // Skip current node
    reader.SkipUntil(cur => cur.NodeType == XmlNodeType.Text);
    Console.WriteLine("The id from XmlTextReader is {0}", reader.Value);
}

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


Вы также можете попробовать LINQ-TO-XML, если вы не заинтересованы в том, чтобы все дерево XML помещалось в память:

using (var stream = new MemoryStream(Encoding.Default.GetBytes(xml)))
{
    var xdoc = XDocument.Load(stream);
    var id = xdoc
        .Root
        .Elements("key")
        .First(element =>
            element.Value == "Id")
        .ElementsAfterSelf("string")
        .First()
        .Value;
    Console.WriteLine("The id from XDocument is {0}", id);
}

Ваш XML выглядит подозрительно похожим на Plist. Похоже, вам нужна библиотека Plist. Вместо того, чтобы изобретать велосипед, просто используйте любую из библиотек, доступных в NuGet. Они решат ваши проблемы с анализом XML-файла.

Если вы настаиваете на синтаксическом анализе XML вручную, забудьте о низкоуровневом классе SAX и просто используйте DOM. Работать с XDocument намного проще Смотрите решение @EugenePodskal.

Другие вопросы по тегам