Какой самый быстрый способ программной проверки правильности XML-файлов в C #? - PullRequest
6 голосов
/ 09 февраля 2009

У меня большие партии файлов XHTML, которые обновляются вручную. Во время фазы обзора обновлений я хотел бы программно проверить правильность файлов. В настоящее время я использую XmlReader , но время, необходимое для среднего процессора, намного больше, чем я ожидал.

Размер файлов XHTML варьируется от 4 КБ до 40 КБ, и проверка занимает несколько секунд на файл. Проверка необходима, но я бы хотел, чтобы время было как можно короче, поскольку проверка выполняется во время чтения файлов на следующем шаге процесса.

Есть ли более быстрый способ сделать простую проверку правильности XML? Может быть, с использованием внешних библиотек XML?


Я могу подтвердить, что проверка «обычного» содержимого на основе XML молниеносно выполняется с помощью XmlReader, и, как предполагается, проблема, по-видимому, связана с тем, что DTD XHTML читается при каждой проверке файла.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Обратите внимание, что в дополнение к DTD также загружаются соответствующие файлы .ent (xhtml-lat1.ent, xhtml-symbol.ent, xhtml-special.ent).

Поскольку полное игнорирование DTD на самом деле не вариант для XHTML, поскольку правильная формация тесно связана с допустимыми объектами HTML (например, & nbsp; будет быстро вводить ошибки проверки, когда мы игнорируем DTD).


Проблема была решена путем использования пользовательского XmlResolver в соответствии с предложением в сочетании с локальными (встроенными) копиями файлов DTD и сущностей.

Я опубликую решение здесь, как только уберу код

Ответы [ 6 ]

5 голосов
/ 09 февраля 2009

Я ожидаю, что XmlReader с while(reader.Read)() {} будет самым быстрым управляемым подходом. Конечно, не нужно секунд , чтобы прочитать 40 КБ ... какой подход ввода вы используете?

Возможно, вам нужно разрешить какие-то внешние (схемы и т. Д.) Объекты? Если это так, вы можете написать пользовательский XmlResolver (устанавливается через XmlReaderSettings), который использует схемы с локальным кэшированием, а не удаленную выборку ...

Следующее делает ~ 300KB практически мгновенно:

    using(MemoryStream ms = new MemoryStream()) {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.CloseOutput = false;
        using (XmlWriter writer = XmlWriter.Create(ms, settings))
        {
            writer.WriteStartElement("xml");
            for (int i = 0; i < 15000; i++)
            {
                writer.WriteElementString("value", i.ToString());
            }
            writer.WriteEndElement();
        }
        Console.WriteLine(ms.Length + " bytes");
        ms.Position = 0;
        int nodes = 0;
        Stopwatch watch = Stopwatch.StartNew();
        using (XmlReader reader = XmlReader.Create(ms))
        {
            while (reader.Read()) { nodes++; }
        }
        watch.Stop();
        Console.WriteLine("{0} nodes in {1}ms", nodes,
            watch.ElapsedMilliseconds);
    }
2 голосов
/ 09 февраля 2009

Создайте объект XmlReader, передав объект XmlReaderSettings, который имеет ConformanceLevel.Document.

Это подтвердит правильность формы.

Эта статья MSDN должна объяснить детали.

1 голос
/ 11 марта 2011

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

  1. используйте HTML Tidy, чтобы очистить ваш xml. установить опцию удаления типа документа
  2. затем прочитайте сгенерированный xhtml / xml из tidy.

вот тот же код

public void GetDocumentStructure(int documentID)
    {
        string scmRepoPath = ConfigurationManager.AppSettings["SCMRepositoryFolder"];
        string docFilePath = scmRepoPath + "\\" + documentID.ToString() + ".xml";

        string docFilePath2 = scmRepoPath + "\\" + documentID.ToString() + "_clean.xml";

        Tidy tidy = new Tidy();
        tidy.Options.MakeClean = true;
        tidy.Options.NumEntities = true;
        tidy.Options.Xhtml = true;
        // this option removes the DTD on the generated output of Tidy
        tidy.Options.DocType = DocType.Omit;

        FileStream input = new FileStream(docFilePath, FileMode.Open);            
        MemoryStream output = new MemoryStream();
        TidyMessageCollection msgs = new TidyMessageCollection();
        tidy.Parse(input, output, msgs);            
        output.Seek(0, SeekOrigin.Begin);

        XmlReader rd = XmlReader.Create(output);            
        int node = 0;

        System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
        while (rd.Read())
        {                
            ++node;                
        }
        watch.Stop();

        Console.WriteLine("Duration was : " + watch.Elapsed.ToString());
    }
1 голос
/ 09 февраля 2009

На моем довольно обычном ноутбуке чтение 250K XML-документа от начала до конца с XmlReader занимает 6 миллисекунд. Кое-что еще, кроме простого разбора XML, является виновником.

0 голосов
/ 10 февраля 2009

Лично я довольно ленивый ... поэтому я ищу .NET библиотеки, которые уже решают проблему. Попробуйте использовать функцию DataSet.ReadXML() и поймайте исключения. Он делает довольно удивительную работу по объяснению ошибок формата XML.

0 голосов
/ 09 февраля 2009

Как уже упоминалось, узким местом, скорее всего, является не XmlReader.

Проверьте, не случится ли вам много конкатенации строк без строителя строк.

Это действительно может нанести удар по вашей производительности.

...