2012-07-04 3 views
2

У меня проблема, над которой я работаю уже довольно давно. У меня есть файл XML с более чем 50000 записями (одна запись имеет 3 уровня). Этот файл используется одним из моих приложений для управления отправкой документа (запись содержит, среди прочих сведений, тип документа, который должен быть отправлен определенному лицу). Поэтому в моем приложении я загружаю XML-файл в XmlDocument, а затем с помощью метода SelectNodes создаю XmlNodeList, из которого я читаю нужные данные. Процесс такой: наш рабочий берет идентификационную карточку человека (простой eith штрих-код) и читает ее с помощью считывателя штрих-кодов. Когда значение штрих-кода было прочитано, мое приложение находит человека с этим идентификатором в XML-файле и сохраняет тип документа в строковой переменной. Затем рабочий берет документ и считывает его штрих-код, и если значение штрих-кода документов и значение в значении в строковой переменной совпадают, приложение делает запись, что документ типа xxxxxxxx будет отправлен лицу с идентификатором yyyyyyyyyy. Это очень простой код, он отлично работает сейчас, и вот как это выглядит: На textBox1_TextChanged события (работник чтения лиц ID):Резка большого XML-файла на более мелкие куски в C#

foreach(XmlNode node in NodeList){ 
if(String.Compare(node.Attributes.GetNamedItem("ID").Value.ToString(),textBox1.Text)==0) 
{ 
ControlString = node.ChildNode[3].FirstChild.Attributes.GetNamedItem("doctype").Value.ToString(); 
break; 
} 
} 
textBox2.Focus(); 

И textBox2_TextChanged случае (рабочий читать документы штрих-код):

if(String.Compare(textBox2.Text,ControlString)==0) 
{ 
//Create a record and insert it into a SQL database 
} 

Мой вопрос - как будет мое приложение выполнять с большими файлами XML (мне сказали, что файл XML может быть до 500000 записей большой), будет такой подход действителен, или мне нужно вырезать файл в файлы меньшего размера. Если мне придется разрезать его, пожалуйста, дайте мне идею с некоторыми примерами кода, я пытался сделать это следующим образом: Чтением всей записи и хранение его в строку:

private void WriteXml(XmlNode record) 
     { 
      tempXML = record.InnerXml; 
      temp = "<" + record.Name + " code=\"" + record.Attributes.GetNamedItem("code").Value + "\">" + Environment.NewLine; 
      temp += tempXML + Environment.NewLine; 
      temp += "</" + record.Name + ">"; 
      SmallerXMLDocument += temp + Environment.NewLine; 
      temp = ""; 
      i++; 
     } 

tempXML, темп и SmallerXMLDocument все строковые переменные.

А потом в методе button_Click я загрузить файл XML в XmlNodeList (опять-таки с помощью XmlDocument.SelectNodes метод), и я стараюсь, чтобы создать одну большую строковое значение, которое будет держать все записи, как это:

foreach(XmlNode node in nodes) 
{ 
if(String.Compare(node.ChildNode[3].FirstChild.Attributes.GetNamedItem("doctype").Value.ToString(),doctype1)==0) 
{ 
    WriteXML(node); 
} 
} 

Моя идея состояла в том, чтобы создать строковое значение (в этом случае называется SmallerXmlDocument), и когда я прохожу через весь XML-файл, просто скопируйте значение этой строки в новый файл. Это работает, но только для файлов, которые имеют до 2000 записей (и у меня есть путь более того). Итак, если мне нужно вырезать файл на более мелкие куски, что было бы лучшим способом сделать это (помните, что в XML-файле может быть до полумиллиона записей)?

Благодаря

+0

Почему вы используете XML для этих огромных данных, почему бы не рассмотреть возможность использования каких-либо СУБД, таких как SQL ect. ??? – yogi

+0

К сожалению, я не один (и не моя компания), который создает и хранит записи, мы получаем его от нашего клиента, поэтому на данный момент у меня нет выбора, кроме как использовать XML-файл. – NDraskovic

ответ

2

Во-первых, я подозреваю, что вы злоупотребляя XML API. Вы можете запросить XmlDocument непосредственно с XPath, чтобы получить результат сразу, без предварительного выбора списка записей и повторения их. Ни в коем случае не нужно преобразовывать части дерева XML в строки.

Подход загрузки всего XML-документа в память будет работать нормально, если вы не возражаете потратить от 50 до 500 мегабайт оперативной памяти в своем приложении.

Если вы хотите сохранить RAM, вы должны использовать XmlReader для потоковой передачи XML с диска.

+0

Я пробовал с XPath (я никогда не работал с ним раньше), но проблема заключается в уровнях каждой записи. Все записи имеют 3 уровня - идентификатор лиц - это атрибут на первом уровне (записи, это второй уровень всего документа), а doctype - атрибут третьего уровня (так что это ребенок ребенка узла, который содержит идентификатор человека). Как бы выглядел XPath, если бы я хотел проверить, какой тип doctype получает определенный человек (я знаю о методе SelectSingleNode, я спрашиваю о запросе XPath)? – NDraskovic

+1

// * [@ id = 'theid'] // * [@ doctype = 'thetype'] на основе того, что вы поставили выше, вернет узел doctype или null, если он не существует –

0

Что нужно знать о том, что вам нужно получить доступ к данным, так как это 50 000 строк в 1 файле или 1000 строк в 50 файлах, у вас одинаковый объем данных.

Ничего не мешает вам использовать что-то SQL-Lite или SQL Server Compact в вашем клиенте. Для этого есть много преимуществ. Вы можете использовать XMLReader для анализа данных в таблицах в вашей БД. Сделав это, вы теперь можете использовать SQL Engine, чтобы найти нужные вам строки, используя объединения, чтобы найти связанные строки намного проще. Вы также не храните огромное количество данных в памяти. Если XML может измениться, то посмотрите файл для изменений & обновите БД, когда это произойдет.

+0

Ну, это поможет, потому что приложение не будет читать сразу все файлы - я бы создавал файлы с записями только с одним типом doctype (например, если есть 4 доктрины, было бы 4 файла) и загружать этот файл в приложение. Таким образом, файл, загруженный приложением, будет содержать около 12 000 записей, что по-прежнему значительно меньше. Что касается использования SQL, я также думал об использовании этого подхода, поэтому я рассмотрю его. благодаря – NDraskovic

Смежные вопросы