Я пытаюсь проанализировать XML-файл с помощью C# в среде.NET, и он продолжает пропускать элементы

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

<azsa:Views>
   <azsa:Spatial_Array>
      <azsa:Spatial>
         <azsa:ViewName>Spatial</azsa:ViewName>
            <azsa:BBox>
               <azsa:PointLo>
                 <azsa:x>0</azsa:x>
                 <azsa:y>0</azsa:y>
                 <azsa:z>0</azsa:z>
                </azsa:PointLo>
               <azsa:PointHi>
                 <azsa:x>2925</azsa:x>
                 <azsa:y>3375</azsa:y>
                 <azsa:z>2775</azsa:z>
               </azsa:PointHi>
             </azsa:BBox>
       </azsa:Spatial>
    </azsa:Spatial_Array>
</azsa:Views>

Я должен прочитать координаты X, Y и Z для PointHi и PointLo

Я использовал класс XMLReader() для выполнения задачи.

XmlTextReader reader = new XmlTextReader(openFileDialog1.FileName);

 while (reader.Read())
 {
   reader.ReadToFollowing("azsa:Views");
   reader.ReadToFollowing("azsa:Spatial_Array");
   reader.ReadToFollowing("azsa:Spatial");
   reader.ReadToFollowing("azsa:ViewName");
   reader.ReadToFollowing("azsa:BBox");
   reader.ReadToFollowing("azsa:PointLo");
   reader.ReadToFollowing("azsa:x");
   low[0] = (int)(Double.Parse(reader.ReadElementString()));
   reader.ReadToFollowing("azsa:y");
   low[1] = (int)(Double.Parse(reader.ReadElementString()));
   reader.ReadToFollowing("azsa:z");
   low[2] = (int)(Double.Parse(reader.ReadElementString()));
   reader.ReadToFollowing("azsa:PointHi");
   reader.ReadToFollowing("azsa:x");
   high[0] = (int)(Double.Parse(reader.ReadElementString()));
   reader.ReadToFollowing("azsa:y");
   high[1] = (int)(Double.Parse(reader.ReadElementString()));
   reader.ReadToFollowing("azsa:z");
   high[2] = (int)(Double.Parse(reader.ReadElementString()));
}

Считыватель работает отлично, пока не достигнет первого x в PointLo, а затем просто перейдет к y в PointHi. Я пытался использовать потомков, поддеревьев и readinnerxml, но он все еще делает то же самое.

ПРИМЕЧАНИЕ: 1. В цикле while имеется больше кода для чтения оставшейся части XML, но он не был необходим для этой проблемы, поэтому я не включил его в статью. 2. Изменить способ организации XML невозможно, потому что именно так они должны храниться для задачи, которую я выполняю. 3. XMLReader является предпочтительным методом, так как я имею дело с большим количеством документов, и нет возможности использовать эту кэш-память.

2 ответа

Решение

У меня была довольно похожая проблема, когда я читал поддеревья. Решением в этом сценарии было удаление поддерева XmlReaders. Конечно, ситуация здесь немного другая, но не могли бы вы рассмотреть такой подход, как приведенный ниже (обратите внимание, что я убрал префиксы элементов для простоты тестирования, а также прочитал в XML-строке, а не в файле)?

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

В качестве примечания, я думаю, что, возможно, большая часть уродства может быть удалена путем создания классов, представляющих различные компоненты (или объекты) в потоке XML, и возложения на эти классы ответственности за разбор их собственных свойств.

Только один способ (из многих я уверен), чтобы снять кожу с кошки...

private void ParseXml(string xml)
{
    double[] low = null;
    double[] hi = null;

    using (StringReader stringReader = new StringReader(xml))
    {
        using (XmlReader xmlReader = XmlReader.Create(stringReader))
        {
            while (xmlReader.Read())
            {
                if (xmlReader.NodeType != XmlNodeType.Element) continue;

                if (xmlReader.Name == "PointLo")
                {
                    low = ParsePoint(xmlReader);
                }
                else if (xmlReader.Name == "PointHi")
                {
                    hi = ParsePoint(xmlReader);
                }
            }
        }
    }
}

private double[] ParsePoint(XmlReader xmlReader)
{
    double[] point = new double[3];

    using (XmlReader pointReader = xmlReader.ReadSubtree())
    {
        while (pointReader.Read())
        {
            if (pointReader.NodeType != XmlNodeType.Element) continue;

            if (pointReader.Name == "x")
            {
                point[0] = GetDimensionValue(pointReader);
            }
            else if (pointReader.Name == "y")
            {
                point[1] = GetDimensionValue(pointReader);
            }
            else if (pointReader.Name == "z")
            {
                point[2] = GetDimensionValue(pointReader);
            }
        }
    }

    return point;
}

private double GetDimensionValue(XmlReader reader)
{
    using (XmlReader dimensionReader = reader.ReadSubtree())
    {
        dimensionReader.Read();

        return reader.ReadElementContentAsDouble();
    }
}

Итак, как я упоминал в комментариях к решению Мандерсона, что по какой-то причине он не видит элемент y как элемент, а вместо этого видит его как текстовый элемент, я внес следующие изменения в цикл while в ParsePoint()

                 while (pointReader.Read())
                  {
                    if (pointReader.NodeType == XmlNodeType.Element || pointReader.NodeType== XmlNodeType.Text)
                     {

                      if (pointReader.Name == "azsa:x")
                       {
                          point[0] = pointReader.ReadElementContentAsDouble();
                       }
                      else if (pointReader.Name == "")
                       {
                          point[1] = Double.Parse(pointReader.Value);
                       }
                     else if (pointReader.Name == "azsa:z")
                       {
                     point[2] = pointReader.ReadElementContentAsDouble();
                       }
                    }
                 }

Хотя я не утверждаю, что это идеальный способ сделать это, он работает для файлов XML, с которыми я имею дело. Я также удалил метод GetDimensionValue и просто делаю чтение значений / элементов в самом методе.

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