Member 12692000 Ответов: 0

Как я могу игнорировать 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-файле, добавлять узлы и т. д... Но это относительно медленно и занимает больше памяти.

Вы сами решаете, что вам нужно использовать - в соответствии с вашими требованиями.

0 Ответов