Там должен быть лучший способ парсинга XML в C#, чем то, что я делаю


Это как я в настоящее время получение данных из XML, но это, кажется, действительно неэффективно, проверяя каждый localname в каждой итерации. Как я должен делать это?

Вот пример XML-кода я пытаюсь разобрать, последовал мой код.

<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <result>
    <properties type="array">
      <property>
        <last-account-review-at>2011-04-26 00:00:04</last-account-review-at>
        <unit-balance type="integer">-104</unit-balance>
        <daily-consumption type="decimal">10.8</daily-consumption>
        <status>active</status>
        <end-date></end-date>
        <icp-number>0001234567RN602</icp-number>
        <address>
          <property-name nil="true"></property-name>
          <flat-number>3</flat-number>
          <suburb>Suburbia</suburb>
          <street-number>21</street-number>
          <region>Nether</region>
          <street-name>Easy</street-name>
          <district>Metropolis</district>
        </address>
        <start-date>2010-05-05</start-date>
        <status-detail nil="true"></status-detail>
      </property>
    </properties>
    <account-number>9001234567</account-number>
  </result>
  <version>1.0</version>
</hash>

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

public static class DataRetrieval
    {

        private static XmlNameTable _nt;
        private static object _propertyElement;
        private static object _unitBalanceElement;
        private static object _dailyConsumptionElement;
        private static object _statusElement;

        static DataRetrieval()
        {
            _nt = new NameTable();
            _propertyElement = _nt.Add("property");
            _unitBalanceElement = _nt.Add("unit-balance");
            _dailyConsumptionElement = _nt.Add("daily-consumption");
            _statusElement = _nt.Add("status");
        }      

        public static bool ParseCustomerData(string raw, out List<PropertyDetails> properties)
        {
            bool parsedOK = false;
            properties = new List<PropertyDetails>();
            PropertyDetails property = null;

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;
            settings.IgnoreWhitespace = true;
            settings.NameTable = _nt;
            XmlReader reader = XmlReader.Create(new StringReader(raw), settings);

            object localname;

            bool continueReading = true;
            int dataItemsRead = 0;
            const int DataItemsToRead = 3;

            try
            {

                while (continueReading)
                {
                    if (reader.IsStartElement())
                    {
                        localname = reader.LocalName;

                        if (localname == _propertyElement)
                        {
                            if (property != null)
                            {
                                if (dataItemsRead == DataItemsToRead)
                                {
                                    properties.Add(property);
                                    dataItemsRead = 0;
                                }
                                else
                                {
                                    break;
                                }

                            }
                            property = new PropertyDetails();
                            continueReading = reader.Read();

                        }
                        else if (localname == _unitBalanceElement)
                        {
                            property.UnitBalance = reader.ReadElementContentAsInt();
                            dataItemsRead++;
                        }
                        else if (localname == _dailyConsumptionElement)
                        {
                            property.DailyConsumption = reader.ReadElementContentAsDouble();
                            dataItemsRead++;
                        }
                        else if (localname == _statusElement)
                        {
                            if (property.SetStatus(reader.ReadElementContentAsString()))
                            {
                                dataItemsRead++;
                            }
                        }
                        else
                        {
                            continueReading = reader.Read();
                        }
                    }
                    else
                    {
                        continueReading = reader.Read();
                    }
                }

            }
            catch (XmlException e)
            {
                Debug.WriteLine("XmlException: {0}", e.Message);
            }

            parsedOK = dataItemsRead == DataItemsToRead;

            if ((property != null) && (parsedOK))
            {
                properties.Add(property);
            }

            return parsedOK;
        }


    }


8450
4
задан 5 июня 2011 в 11:06 Источник Поделиться
Комментарии
3 ответа

Взгляните на


LINQ для XML-файле (в MSDN)

Преподобный Скотт ГУ имеет хороший кусок LINQ для XML-файле здесь. Это должно помочь вам начать работу!

Использование LINQ в XML должен сделать код легче читать и поддерживать.

8
ответ дан 6 июня 2011 в 01:06 Источник Поделиться

Вы можете попробовать использовать XDocument используется вместо.

Кроме того, это позволит увидеть пример XML-кода Вы пытаетесь разобрать для того, чтобы правильно предложить рефакторинг кода.

Редактировать:
Вы можете сделать это (XDocument используется + для LINQ):

string sXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<hash>
<result>
<properties type=""array"">
<property>
<last-account-review-at>2011-04-26 00:00:04</last-account-review-at>
<unit-balance type=""integer"">-104</unit-balance>
<daily-consumption type=""decimal"">10.8</daily-consumption>
<status>active</status>
<end-date></end-date>
<icp-number>0001234567RN602</icp-number>
<address>
<property-name nil=""true""></property-name>
<flat-number>3</flat-number>
<suburb>Suburbia</suburb>
<street-number>21</street-number>
<region>Nether</region>
<street-name>Easy</street-name>
<district>Metropolis</district>
</address>
<start-date>2010-05-05</start-date>
<status-detail nil=""true""></status-detail>
</property>
</properties>
<account-number>9001234567</account-number>
</result>
<version>1.0</version>
</hash>";

var xml = XDocument.Parse(sXml);

var r = from x in xml.Descendants("property")
select new
{
unitBalance = x.Element("unit-balance").Value,
dailyConsumption = x.Element("daily-consumption").Value,
status = x.Element("status").Value
};

this._propertyElement = xml.Descendants("property");
this._unitBalanceElement = r.ElementAt(0).unitBalance;
this._dailyConsumptionElement = r.ElementAt(0).dailyConsumption;
this._statusElement = r.ElementAt(0).status;

Примечание: не включать любые проверки ошибок, просто хотел показать некоторые возможности.

7
ответ дан 6 июня 2011 в 12:06 Источник Поделиться

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

Если вам не нравится xsd.exe xsd2code является еще одной альтернативой для генерации кода.

0
ответ дан 6 июня 2011 в 03:06 Источник Поделиться