загрузить весь XML-документ, и, поскольку (b) ваш код, скорее всего, приведет к неверному XML-документу (а именно к одному с двумя корневыми узлами документа).

я есть очень базовая структура / файл XML на диске, который выглядит примерно так:

<root>
    <data timestamp="dd-mm-yyyy" type="comment">kdkdkdk</data>
    <data timestamp="dd-mm-yyyy" type="event">kdkdkdkgffgfdgf</data>
    <data timestamp="dd-mm-yyyy" type="something">kddsdsfsdkdkdk</data>
</root>

XML будет, как уже упоминалось, во внешнем файле на диске. Поскольку файл может вырасти довольно большим (фактически «обрезается» каждые пару недель), я не хочу сначала загружать файл XML, чтобы добавить новый узел ...

Есть ли способ добавить новый узел, как это? его можно просто добавить в верхнюю / нижнюю часть и т. д., поскольку процесс, который фактически использует XML, в любом случае сортирует его по метке времени.

Я предполагаю грубый способ добавить узел в виде текста ... однако я думаю, что это добавит узел ПОСЛЕ конечного тега ??

Любые идеи с благодарностью получили .. Дэвид.

Ответы на вопрос(8)

Вы можете открыть файл как текст, найти положение</root> и начать переписывать оттуда. И, конечно, добавить</root> очередной раз.

Быстрый и грязный подход, это не очень надежно:

убедитесь, что вы подготовили исходный файл, там должно бытьничего (без пробелов) после закрывающего тегаубедитесь, что вы используете кодировку ASCII или UTF8

====

string closeTag = "</root>";
int closeLength = Encoding.UTF8.GetBytes(closeTag).Length;

var fs = System.IO.File.Open(filename, System.IO.FileMode.Open);
fs.Position = fs.Length - closeLength;

var writer = new StreamWriter(fs);  // after the Position is set

writer.WriteLine(newTag);
writer.Write(closeTag);  // NOT WriteLine !!

writer.Close();
fs.Close();

И конечно вы знаете об использованииusing() {} блоки.

 Dav.id23 янв. 2011 г., 13:04
@Henk: О, правильно, спасибо, посмотрю на это!
 Dav.id23 янв. 2011 г., 12:41
Да, правда .. На самом деле amcashcow только что прокомментировал выше об этом .. так что спасибо!
 TToni23 янв. 2011 г., 12:47
Вы можете сделать это с помощью XML API (XmlReader / XmlWriter). Это нелегко реализовать (в зависимости от возможного содержимого файла XML), но выполнимо. Если у вас есть только основные теги и атрибуты, как указано выше, это даже не составит труда.
 Henk Holterman23 янв. 2011 г., 13:13
@Ttoni: сложная часть - найти начало</root>и XmlReader не подходит для этого. @David потребуется Encoding.GetBytes () и некоторое сравнение байтов [].
 Henk Holterman23 янв. 2011 г., 12:43
@ Дэвид: НЕТ, я имел в видуне читать все это, но использовать Stream.Position.
Решение Вопроса

но просто для того, чтобы еще раз обсудить это, вы уверены, что эти данные должны храниться в виде файла XML?

Данные, которые вы храните, выглядят довольно просто (то есть запись с тремя полями, датой, типом и некоторыми строковыми данными. Если вам не нужны какие-либо дополнительные преимущества, предоставляемые XML (глянь сюда) тогда почему бы просто не использовать базовый CSV? Таким образом, вы можете просто продолжать добавлять к нему, как файл журнала черезFile.AppendText("filename").

(Черт, возможно, даже можно использовать что-то вроде log4net для управления журналированием и любой другой уборкой.)

 Henk Holterman23 янв. 2011 г., 13:19
Да, это может быть разумным способом обойти проблему.
 Dav.id23 янв. 2011 г., 22:36
Спасибо, на самом деле всем, некоторые хорошие идеи наверняка. Одна из единственных причин использования XML (и того факта, что в существующей системе уже есть некоторые данные) - возможность загружать XML напрямую в набор данных / таблицу для использования с некоторым существующим кодом ... но с учетом комментариев Исходя из этого вопроса и задержки, которую я имею для загрузки данных позже, вариант CSV, вероятно, является подходящим ... (хотя опция stream.position Хенка тоже не так уж и плоха!) Еще раз спасибо !!

Если вы хотите сделать это «правильным» способом, вы должны прочитать файл и XML в нем. Вы можете избежать полной загрузки в память, например, используя класс XmlReader.

Однако, если вы точно знаете текстовую разметку и кодировку файла, вы можете избежать чтения и перезаписи полностью, открыв его как файл с произвольным доступом (FileStream), пропустив до конца (минус "<root /> "), добавьте туда новую запись и снова напишите" <root /> ".

не загружая XML, вы подразумеваете, что не создаете дерево DOM, VTD-XML является единственным API, который позволяет вам вырезать или разделять вставки или изменять их постепенно. Кроме того, поскольку VTD-XML эффективно использует память, вам не придется беспокоиться о размере XML-документа. Подобный пост в Java находится наКак обновить большой файл XML, Обратите внимание, что vtd-xml доступен на Java, C #, C и C ++.

 Henk Holterman23 янв. 2011 г., 22:50
ОК, я полагаю, ваше имя пользователя считается раскрытием.
 BoltClock♦01 февр. 2011 г., 02:02
@John Saunders @Henk Holterman: Это может или не может быть рассмотрено как раскрытие, но это, конечно же, черт возьми, все выглядит так, будто он здесьтолько что продвигать свой продукт.
 Dav.id25 янв. 2011 г., 05:08
Не слышал об этом .. на самом деле, вероятно, излишним для этого решения, возможно, но определенно проверим это ..
 John Saunders01 февр. 2011 г., 02:03
@BoltClock: я просто не думаю, что это так сложно раскрыть, что я извиняю его за то, что он не раскрывает. Это была постоянная проблема с ним.
 John Saunders01 февр. 2011 г., 01:46
@Henk: я не согласен, и был отмечать его спамом (за исключением одного ответа, который я проголосовал).
System.IO.FileInfo[] aryFi = di.GetFiles("*.xml");


foreach (System.IO.FileInfo fi in aryFi) {

 System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
 xmlDocument.Load(fi.FullName);

 XmlNode refelem = xmlDocument.LastChild;
 XmlNode newElem = xmlDocument.CreateNode("element", "something", "");
 newElem.InnerText = "sometext";
 xmlDocument.InsertAfter(newElem, refelem);
}

что открытие и вставка узла будет лучшим вариантом. В любом случае вам нужно будет использовать IO, почему бы не сделать это правильно?

Для одного файла

System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
 xmlDocument.Load("file path");

 XmlNode refelem = xmlDocument.LastChild;
 XmlNode newElem = xmlDocument.CreateNode("element", "something", "");
 newElem.InnerText = "sometext";
 xmlDocument.InsertAfter(newElem, refelem);
 Ismail23 янв. 2011 г., 13:28
Если бы я оказался в такой ситуации, и поскольку оба подхода требуют от вас выполнения вызова ввода-вывода, то для меня предпочтительнее было бы добавить узел XML вместо текста, у вас могут быть некоторые причины планировать сделать это таким образом.
 Henk Holterman23 янв. 2011 г., 13:18
Это*.xml кажется, пришли из ниоткуда. И это по-прежнему загружает весь файл (и некоторые другие), вопрос заключается в том, чтобы избежать этого.
 Ismail23 янв. 2011 г., 13:20
Да, это было, если вы хотите выполнить одно и то же действие для всех XML-файлов в каталоге. Перед тем, как получить информацию каталога, есть код. В вашем случае вы не будете перебирать все файлы. Я собираюсь добавить код для одного файла.

поскольку вы не можете просто добавить узел в документ.

Файл Xml может иметь только один корень, поэтому новый узел необходимо будет добавить после последнего элемента данных, но до тега закрытия корня. В противном случае XML не является допустимым.

 Dav.id23 янв. 2011 г., 12:37
Да, правда .. Я понимаю, что, вероятно, будет так ... но подумал, почему бы не задать вопрос в любом случае! так, на всякий случай!

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

просто используйте

string s = File.ReadAllText(path)
s = s.replace("</root>", newnode + "</root>")
Fil,e.WriteAllText(s, path)
 Arseni Mourzenko23 янв. 2011 г., 12:44
-1. Вопрос об открытии больших файлов. Я не уверен, что загрузка большого файла в память - лучший подход, когда для этого есть потоки.
 amcashcow23 янв. 2011 г., 12:47
Я думаю, тогда вам нужно знать физический адрес на диске и каким-то образом писать прямо на него. если бы это была таблица в базе данных, я думаю, что может избежать чтения
 Henk Holterman23 янв. 2011 г., 12:38
Это все еще загружает это ... Это просто пропускает синтаксический анализ XML, незначительное сохранение. Ввод / вывод дорогой.
 Dav.id23 янв. 2011 г., 12:40
Круто ... хороший простой способ добавить новый узел ... Я думаю, это все еще означает чтение файла xml, но потом я догадался, что так оно и будет, так что спасибо за это, хороший чистый пример!
 stakx23 янв. 2011 г., 12:52
-1 потому что (а) ФП явно попросил решение, которое делаетне загрузить весь XML-документ, и, поскольку (b) ваш код, скорее всего, приведет к неверному XML-документу (а именно к одному с двумя корневыми узлами документа).

Ваш ответ на вопрос