Суммирование атрибутов XML иногда возвращает ноль - PullRequest
0 голосов
/ 18 ноября 2011

Я пытаюсь проанализировать файл NZB (который является XML) и суммировать атрибуты байтов.Иногда это работает отлично, а иногда возвращает ноль, и я не могу понять, почему.Насколько я могу судить, файлы NZB имеют идентичную структуру.

private Int32 processNZB(string sFilename)
{
    XDocument xFile = XDocument.Load(sFilename);

    Int32 sum = xFile.Descendants("segment").Sum(x => (int)x.Attribute("bytes"));

    sum = (int)(sum / 1024 / 1024); // bytes -> MB
    return sum;
}

Исходный код и примеры файлов можно найти здесь: http://jonathanslaven.com/.for/.stackoverflow/

Есть ли очевидная причина, по которой это не так?за работой?Есть ли лучший способ сделать это?Спасибо за вашу помощь.

Ответы [ 3 ]

2 голосов
/ 18 ноября 2011

Возможно, начальное значение суммы меньше 1024 2 байтов? Когда вы выполняете целочисленное деление, результат будет переигран, поэтому все, что меньше 1024 2 байтов, вернет ноль.

Например, пример файла NZB @ wikipedia выдаст 0 при запуске через ваш алгоритм.

EDIT:

После проверки «плохих» файлов (на самом деле, это «хороший» файл, который не соответствует спецификации), причина, по которой он не работает, заключается в том, что пространство имен по умолчанию корневого элемента равно "http://www.newzbin.com/DTD/2003/nzb", что означает любой дочерний элемент узлы будут наследовать это пространство имен.

Это означает, что ваш запрос .Descendants("segment") не возвращает узлов. Прикрепление правильного пространства имен устраняет проблему.

Ниже показано, как вы можете изменить свой код для чтения такого файла.

private int ProcessNzb(string sFilename)
{
    XDocument xDoc = XDocument.Load(sFilename);
    return xDoc
        .Descendants(xDoc.Root.Name.Namespace + "segment")
        .Sum(x => (int) x.Attribute("bytes")) / 1024 / 1024;
}

Кроме того, я бы не стал публиковать файлы, которые предполагают участие в контрабанде.

2 голосов
/ 18 ноября 2011

Возможно ли, что сумма достаточно мала, чтобы ее можно было округлить до 0 при делении на 1024 с использованием целочисленного деления?

Пример:

int sum = 300; //300
int sumDividedOnce = sum/1024; // 0
int sumDividedTwice = sumDividedOnce/1024; // 0
1 голос
/ 18 ноября 2011

Это работает, если вы измените

Int32 sum = xFile.Descendants("segment").Sum(x => (int)x.Attribute("bytes"));

до

Int32 sum = xFile.Descendants("segment").Sum(x => int.Parse(x.Attribute("bytes").Value));
...