Что такое XmlNodeType.Document? Разница между XmlNodeType.Element и XmlNodeType.Document - PullRequest
1 голос
/ 12 октября 2009

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

XML

<?xml version="1.0" encoding="utf-8"?>
<NewsLetters>
  <EMail Date="10/10/2009">hello@hello.com</EMail>
  <EMail Date="10/10/2009">hello@hello.com</EMail>
  <EMail Date="10/10/2009">hello@hello.com</EMail>
  <EMail Date="10/10/2009">hello@hello.com</EMail>
</NewsLetters>

C # код:

public static string TotalMemberCount()
{
    XmlTextReader reader = new XmlTextReader(HttpContext.Current.Server.MapPath("~/Newsletter/NewsLetter.xml"));

    int totalCount = 0;
    while (reader.Read())
    {
        if (reader.NodeType == XmlNodeType.Element && reader.NodeType != XmlNodeType.Document)
            totalCount++;
    }

    return totalCount.ToString();
}

Обычно я ожидал 4 записи, но он возвращает 5, потому что он также учитывает корневой элемент. Что мне делать? На самом деле я знаю, как решить с помощью XDocument, XElement и LINQ, но я хочу решить таким образом, не спрашивайте меня, почему, потому что я хочу научиться каждому способу решения таких проблем.

Заранее спасибо.

С уважением ....

Ответы [ 2 ]

2 голосов
/ 12 октября 2009

Ответ, который вы придумали, имеет как минимум пять разных недостатков.

  1. Это, конечно, не «универсальное решение», поскольку ваш код теперь полностью зависит от информации в XML - ваш метод может правильно считать элементы только в том случае, если обрабатываемый им документ XML содержит атрибут flag, который вы добавили .

  2. Атрибут флага не нужен. Каждый раз, когда XmlReader начинается в начале потока, который он читает, первый элемент, который он читает, это всегда , который будет элементом верхнего уровня. Это не может быть ничего другого. Вместо добавления атрибута в ваш документ для идентификации элемента верхнего уровня, вы можете просто использовать флаг, чтобы отслеживать, прочитали ли вы элемент верхнего уровня или нет. Или, черт возьми, вы можете просто вычесть 1 из общего числа.

  3. И даже если вам нужен атрибут flag, вы делаете это неправильно. Вы используете MoveToFirstAttribute, чтобы найти его. Что если в элементе более одного атрибута? Что если первый атрибут, найденный вашим кодом, значение которого True не Root? А что если у одного из дочерних элементов есть атрибут с этим значением? Если вы собираетесь использовать атрибут для этой цели, вам следует, по крайней мере, очень искать его по имени.

  4. Этот код не будет учитывать все элементы child элемента верхнего уровня, он будет учитывать все элементы Потомки . Считыватель перемещается от узла к узлу в порядке документа. Если у узла элемента есть дочерний узел, этот дочерний узел является следующим узлом, который будет считан Read(). Существуют методы XmlReader, которые можно использовать для чтения всего элемента и всего его содержимого за один прием, но вы их не используете.

  5. Условие reader.NodeType != XmlNodeType.XmlDeclaration && reader.NodeType == XmlNodeType.Element является избыточным: невозможно, чтобы узел мог быть объявлением XML, если он является элементом.

0 голосов
/ 12 октября 2009

В любом случае, я нашел свое собственное решение, и я пытался достичь общего решения, поэтому я нашел такое решение:

XML

<?xml version="1.0" encoding="utf-8"?>
<NewsLetters Root="True">
  <EMail Date="10/10/2009">hello@hello.com</EMail>
  <EMail Date="10/10/2009">hello@hello.com</EMail>
  <EMail Date="10/10/2009">hello@hello.com</EMail>
  <EMail Date="10/10/2009">hello@hello.com</EMail>
</NewsLetters>

C #

   public static string TotalMemberCount()
    {
        int totalCount = 0;
        using (XmlTextReader reader = new XmlTextReader(HttpContext.Current.Server.MapPath("~/Newsletter/NewsLetter.xml")))
        {
            while (reader.Read())
            {
                if (reader.NodeType != XmlNodeType.XmlDeclaration && reader.NodeType == XmlNodeType.Element)
                {
                    if (reader.MoveToFirstAttribute())
                    {
                        if (reader.Value == "True")
                            //gotcha, I don't want this,this is root element
                            continue;
                    }
                    totalCount++;
                }
            }
            return totalCount.ToString();
        }

    }
...