Как я могу игнорировать dtd, обрабатывающий мою программу?
Привет, я пытаюсь создать программу, которая находит, есть ли 3 или более последовательных узлов определенного типа, и показывает их в консоли.
Например, если мой файл содержит последовательные узлы в формате
<xref ref-type="bibr" rid="ref11">[11]</xref>, <xref ref-type="bibr" rid="ref12">[12]</xref>, <xref ref-type="bibr" rid="ref13">[13]</xref>
затем это печатается на консоли, однако <xref ref-type="bibr" rid="ref11">[11]</xref>, <xref ref-type="bibr" rid="ref12">[12]</xref>, <xref ref-type="bibr" rid="ref14">[14]</xref>
как то rid
значение формы увеличено с 12 до 14, оно должно находить совпадения только тогда, когда rid
значение-это приращение на +1.В любом случае, приведенный ниже код делает свою работу
Что я уже пробовал:
using System; using System.Collections.Generic; using System.Linq; using System.IO; using System.Text; using System.Xml; using System.Text.RegularExpressions; namespace CityRemover { class Program { public static void Main(string[] args) { string[] files=Directory.GetFiles(@"D:\test\Jobs\12335","*.xml"); foreach (var file in files) { XmlDocument doc = new XmlDocument(); doc.PreserveWhitespace = true; doc.Load(file); //only selects <p>'s that already have 3 or more refs. No need to check paragraphs that don't even have enough refs XmlNodeList nodes = doc.DocumentElement.SelectNodes("//*[count(xref[@ref-type='bibr' and starts-with(@rid,'ref')])>2]"); List<string> results = new List<string>(); //Foreach <p> foreach (XmlNode x in nodes) { XmlNodeList xrefs = x.SelectNodes(".//xref[@ref-type='bibr' and starts-with(@rid,'ref')]"); List<StartEnd> startEndOfEachTag = new List<StartEnd>(); // we mark the start and end of each ref. string temp = x.OuterXml; //the paragraph we're checking //finds start and end of each tag xref tag foreach (XmlNode xN in xrefs){ //We find the start and end of each paragraph StartEnd se = new StartEnd(temp.IndexOf(xN.OuterXml), temp.IndexOf(xN.OuterXml) + xN.OuterXml.Length); startEndOfEachTag.Add(se); } /* This comment shows the regex command used and how we build the regular expression we are checking with. string regexTester = Regex.Escape("<xref ref-type=\"bibr\" rid=\"ref2\">2</xref>")+"([ ]|(, ))" + Regex.Escape("<xref ref-type=\"bibr\" rid=\"ref3\">3</xref>"); Match matchTemp = Regex.Match("<xref ref-type=\"bibr\" rid=\"ref2\">2</xref> <xref ref-type=\"bibr\" rid=\"ref3\">3</xref>", regexTester); Console.WriteLine(matchTemp.Value);*/ //we go through all the xrefs for (int i=0; i<xrefs.Count; i++) { int newIterator = i; //This iterator prevents us from creating duplicates. string regCompare = Regex.Escape(xrefs[i].OuterXml); // The start xref int count = 1; //we got one xref to start with we need at least 3 string tempRes = ""; //the string we store the result in int consecutive = Int32.Parse(xrefs[i].Attributes["rid"].Value.Substring(3)); for (int j=i+1; j<xrefs.Count; j++) //we check with the other xrefs to see if they follow immediately after. { if(consecutive == Int32.Parse(xrefs[j].Attributes["rid"].Value.Substring(3)) - 1) { consecutive++; } else { break; } regCompare += "([ ]|(, ))" + Regex.Escape(xrefs[j].OuterXml); //we check that the the xref comes exactly after a space or a comma and space Match matchReg; try { matchReg = Regex.Match(temp.Substring(startEndOfEachTag[i].start, startEndOfEachTag[j].end - startEndOfEachTag[i].start), regCompare); //we get the result } catch { i = j; // we failed and i should start from here now. break; } if (matchReg.Success){ count++; //it was a success so we increment the number of xrefs we matched tempRes = matchReg.Value; // we add it to out temporary result. newIterator = j; //update where i should start from next time. } else { i = j; // we failed and i should start from here now. break; } } i = newIterator; if (count > 2) { results.Add(tempRes); } } } Console.WriteLine("Results: {0}",file.ToString()); foreach(string s in results) { Console.WriteLine(s+"\n"); } } Console.ReadKey(); } } class StartEnd { public int start=-1; public int end = -1; public StartEnd(int start, int end) { this.start = start; this.end = end; } } }
Однако я получаю ошибки обработки dtd в некоторых файлах, так как в файле объявлен dtd, и я хочу его игнорировать.
Так что я попробовал
XmlReaderSettings settings = new XmlReaderSettings();
settings.XmlResolver = null;
settings.DtdProcessing = DtdProcessing.Ignore;
FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);
XmlReader reader = XmlTextReader.Create(fs, settings);
XmlDocument doc = new XmlDocument();
doc.Load(reader);
вместо
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load(file);
Я не получаю никаких ошибок, но соответствующие выражения также не отображаются. Хотя я не очень хорошо знаком с Filestream. Может ли кто-нибудь сказать, где я делаю это неправильно?
________________
По моему мнению, используйте try-catch вместо of-else - плохая идея.
Что-то происходит, вы не знаете что, и продолжаете... не хороший.
Проверьте все данные задолго до этого - решите, что вы должны делать, если null, если пусто и так далее.
Member 12692000
Ну, программа работает без каких-либо проблем до сих пор (для файлов без объявления dtd с использованием вышеприведенного опубликованного кода)...мой главный вопрос состоял в том, является ли мой подход к игнорированию dtd правильным или нет? Я не очень хорошо разбираюсь в использовании потоков, поэтому я надеялся, что кто-то может указать, есть ли проблема в этой части кода?
________________
Я сомневаюсь, что поток в .NET может быть причиной этого.
Это стандартный объект для оценки файлов, он используется везде, когда вы используете файл.LoadAllText() или doc.Load(file) - поток работает внутри.
Member 12692000
Является ли мой подход к использованию потока правильным?
________________
Это зависит от размера файла. Если файл действительно большой - 1 гигабайт, 100 МБ и 10 файлов одновременно - .NET дает возможность читать его частично через поток (я говорю о локальном файле на диске).
Если вам нужно прочитать один XML размером даже 30 мб - просто используйте существующие функции, которые могут это сделать. Теперь компьютер имеет 4 ГБ оперативной памяти. Пользоваться им не возбраняется.
________________
XmlReader - может только читать файл вперед, его поток может быть подключен к сетевому файлу. Его преимущества-это производительность и легкий вес.
Объект XmlDocument - можно построить и изменить загружается XML-файле, добавлять узлы и т. д... Но это относительно медленно и занимает больше памяти.
Вы сами решаете, что вам нужно использовать - в соответствии с вашими требованиями.