Чтение вложенного поддерева с помощью XmlReader

Я столкнулся с проблемой при разборе XML в базу данных. Моя структура XML выглядит так:

<atrists>
<artist>
<images>
<image/>
</images>
<id>
</id>
</artist>
</artists>

Там много обоих тегов исполнителей. а в artist много тегов.

Чем я занимаюсь на данный момент:

while (reader.ReadToFollowing("artist"))
{
 XmlReader reader2 = reader.ReadSubtree();
while (reader2.Read())
{
 if (reader2.NodeType == XmlNodeType.Element)
  {
  if (reader2.Name == "images")
  {
 while (reader2.ReadToFollowing("image"))
  {
//here i am adding all images data to lists to query it later
  }
  }
if (reader2.Name == "id")
{
 id = reader2.ReadElementContentAsInt();
}
}

//здесь я хочу сделать SQL-запрос, который добавит много изображений и идентификаторов, прикрепленных к каждому из них.

}

Этот идентификатор не работает должным образом. Он пропускает около 50% идентификаторов или вообще не меняется. Но я вижу там все возможные изображения. Поэтому я думаю, что у меня проблема с переходом от узла к узлу. Любые идеи?


person Whencesoever    schedule 14.07.2014    source источник
comment
Рассмотрите возможность изучения и использования System.Xml.Linq. Ваша задача значительно упростится.   -  person Darek    schedule 14.07.2014
comment
этот файл имеет размер 1 ГБ =) не может его использовать.   -  person Whencesoever    schedule 14.07.2014
comment
Чтение XML-файлов размером 1 ГБ с помощью LINQ не является проблемой, если у вас есть ОЗУ для резервного копирования. Еще одна мысль: возможно, вы могли бы десериализовать конкретный класс?   -  person Darek    schedule 14.07.2014
comment
Ссылка на пример десериализации: stackoverflow.com/questions/364253/   -  person Darek    schedule 14.07.2014
comment
Я только что сохранил XML-файл размером 1 ГБ с помощью LINQ ... занял около 9 ГБ моей оперативной памяти ... :)   -  person Darek    schedule 14.07.2014
comment
на тестовом сервере у меня всего 3 Гб ОЗУ и я этим занимаюсь =)   -  person Whencesoever    schedule 14.07.2014


Ответы (1)


Попробуйте это тогда:

    async Task BigFileReader(System.IO.Stream stream)
    {
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Async = true;
        bool bIdEncountered = false;

        using (XmlReader reader = XmlReader.Create(stream, settings))
        {
            while (await reader.ReadAsync())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        bIdEncountered = reader.LocalName.Equals("id");
                        break;
                    case XmlNodeType.Text:
                        var value = await reader.GetValueAsync();
                        if(bIdEncountered) Console.WriteLine("Run my SQL for {0}", value);
                        break;
                    case XmlNodeType.EndElement:
                        break;
                    default:
                        break;
                }
            }
        }
    }

Пример 2

Возможно, это даст вам лучший пример:

    async Task BigFileReader(System.IO.Stream stream)
    {
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Async = true;
        bool bIdEncountered = false;
        bool bImageEncountered = false;
        List<string> images = new List<string>();
        int artistId = 0;

        using (XmlReader reader = XmlReader.Create(stream, settings))
        {
            while (await reader.ReadAsync())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        bIdEncountered = reader.LocalName.Equals("id");
                        bImageEncountered = reader.LocalName.Equals("image");
                        if(reader.LocalName.Equals("images")) images.Clear();
                        break;
                    case XmlNodeType.Text:
                        //var value = await reader.GetValueAsync();
                        if (bIdEncountered) artistId = Convert.ToInt32(await reader.GetValueAsync());
                        if (bImageEncountered) images.Add(await reader.GetValueAsync());
                        break;
                    case XmlNodeType.EndElement:
                        if (reader.LocalName.Equals("artist")) Console.WriteLine("Saving artist {0} with images {1}", artistId, String.Join(",", images));
                        break;
                    default:
                        break;
                }
            }
        }
    }

Пример с атрибутами

    async Task BigFileReader(System.IO.Stream stream)
    {
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Async = true;
        bool bIdEncountered = false;
        List<ImageNode> images = new List<ImageNode>();
        int artistId = 0;

        using (XmlReader reader = XmlReader.Create(stream, settings))
        {
            while (await reader.ReadAsync())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        bIdEncountered = reader.LocalName.Equals("id");
                        //bImageEncountered = reader.LocalName.Equals("image");
                        if(reader.LocalName.Equals("images")) images.Clear();
                        if (reader.LocalName.Equals("image"))
                        {
                            images.Add( new ImageNode
                                    {
                                        Width = Convert.ToInt32(reader.GetAttribute("width")),
                                        Height = Convert.ToInt32(reader.GetAttribute("height")),
                                        Url = reader.GetAttribute("uri")
                                    });
                        }
                        break;
                    case XmlNodeType.Text:
                        if (bIdEncountered) artistId = Convert.ToInt32(await reader.GetValueAsync());
                        break;
                    case XmlNodeType.EndElement:
                        if (reader.LocalName.Equals("artist")) Console.WriteLine("Saving artist {0} with images {1}", artistId, String.Join(",", images));
                        break;
                    default:
                        break;
                }
            }
        }
    }


internal class ImageNode    
{
    public int Width { get; set; }

    public int Height { get; set; }

    public string Url { get; set; }

    public override string ToString() { return String.Format("{0}x{1}:{2}", Width, Height, Url); }
}

Синхронная версия (VS2010)

    static void BigFileReader(System.IO.Stream stream)
    {
        XmlReaderSettings settings = new XmlReaderSettings();
        bool bIdEncountered = false;
        List<ImageNode> images = new List<ImageNode>();
        int artistId = 0;

        using (XmlReader reader = XmlReader.Create(stream, settings))
        {
            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        bIdEncountered = reader.LocalName.Equals("id");
                        //bImageEncountered = reader.LocalName.Equals("image");
                        if (reader.LocalName.Equals("images")) images.Clear();
                        if (reader.LocalName.Equals("image"))
                        {
                            images.Add(new ImageNode
                            {
                                Width = Convert.ToInt32(reader.GetAttribute("width")),
                                Height = Convert.ToInt32(reader.GetAttribute("height")),
                                Url = reader.GetAttribute("uri")
                            });
                        }
                        break;
                    case XmlNodeType.Text:
                        if (bIdEncountered) artistId = Convert.ToInt32(reader.Value);
                        break;
                    case XmlNodeType.EndElement:
                        if (reader.LocalName.Equals("artist")) Console.WriteLine("Saving artist {0} with images {1}", artistId, String.Join(",", images));
                        break;
                    default:
                        break;
                }
            }
        }
    }
person Darek    schedule 14.07.2014
comment
ты уверен, что это то, что мне нужно? прочитав и добавив свои изображения, я получил всю необходимую информацию о них в списках. Я просто не могу получить идентификатор, один простой int, который находится в теге на том же уровне, что и изображения: (. - person Whencesoever; 14.07.2014
comment
Без особых подробностей о том, что должна делать ваша программа, я не могу дать вам ответ лучше, чем этот. Я уверен, что это даст вам все ваши идентификаторы. XmlReader в этом примере читает файл построчно, точнее, поэлементно, и вы должны реагировать соответствующим образом. Например, вы можете перенести логику выполнения на закрывающий элемент для исполнителя. В приведенном выше примере я оставил эти точки открытыми для изменения вами. Если бы вы дали более подробное описание, чего именно вы пытаетесь достичь. Я мог бы сделать больше. - person Darek; 14.07.2014
comment
ссылка это часть моего файла. Для каждого тега изображения в нем мне нужно сделать запрос в SQL. Query = "insert into myTable values (" + id + ", " + Height + ", " + Width + ", '" + Type + "', '" + Uri + "', '" + Uri150 + "')"; Этот идентификатор предназначен для многих тегов изображений, и у меня все время возникают проблемы с его правильным предоставлением. - person Whencesoever; 14.07.2014
comment
У меня проблема. Установлена ​​Visual Studio 2010, и она не использует асинхронность. - person Whencesoever; 15.07.2014
comment
Вы знаете, как переписать его для синхронных методов? - person Darek; 15.07.2014