xmlreader новая строка \ n вместо \ r \ n

Когда я использую XmlReader.ReadOuterXml (), элементы разделяются \ n вместо \ r \ n. Так, например, если у меня есть представитель XmlDocument из

<A>
<B>
</B>
</A>

я получил

<A>\n<B>\n</B>\n</A>

Есть ли возможность указать символ новой строки? У XmlWriterSettings он есть, но у XmlReader его, похоже, нет.

Вот мой код для чтения xml. Обратите внимание, что XmlWriterSettings по умолчанию имеет NewLineHandling = Replace

XmlDocument xmlDocument = <Generate some XmlDocument>
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;

// Use a memory stream because it accepts UTF8 characters.  If we use a 
// string builder the XML will be UTF16.
using (MemoryStream memStream = new MemoryStream())
{
    using (XmlWriter xmlWriter = XmlWriter.Create(memStream, settings))
    {
        xmlDocument.Save(xmlWriter);
    }

    //Set the pointer back to the beginning of the stream to be read
    memStream.Position = 0;
    using (XmlReader reader = XmlReader.Create(memStream))
    {
        reader.Read();
        string header = reader.Value;
        reader.MoveToContent();
        return "<?xml " + header + " ?>" + Environment.NewLine + reader.ReadOuterXml();
    }
}

person user156144    schedule 25.11.2009    source источник
comment
Это еще более проблематично, когда входной xml содержит сочетание \ r \ n и \ n, и когда нижестоящая система чувствительна к разнице между ними, например XML-документ является промежуточным состоянием для выполнения преобразования xslt перед кодированием вывода в плоский файл с определенными разделителями.   -  person David Burg    schedule 21.04.2017


Ответы (5)


XmlReader автоматически нормализует \r\n\ до \n. Хотя это кажется необычным для Windows, на самом деле это требуется спецификацией XML (http://www.w3.org/TR/2008/REC-xml-20081126/#sec-line-ends).

Вы можете сделать String.Replace:

string s = reader.ReadOuterXml().Replace("\n", "\r\n");
person Jason Kresowaty    schedule 25.11.2009
comment
Ради кроссплатформенной совместимости я бы предложил .Replace("\n", Environment.NewLine), но если ваша среда исправлена, функциональность идентична. - person Flynn1179; 27.01.2020

Мне пришлось записать данные базы данных в XML-файл и прочитать их обратно из XML-файла, используя LINQ to XML. Некоторые поля в записи сами по себе были строками XML с символами \ r. Они должны были остаться нетронутыми. Я потратил дни, пытаясь найти что-то, что подойдет, но похоже, что Microsoft намеренно преобразовала \ r в \ n.

Для меня работает следующее решение:

Чтобы записать загруженный XDocument в XML-файл, сохраняя неизменным \ r, где xDoc - это XDocument, а filePath - это строка:

XmlWriterSettings xmlWriterSettings = new XmlWriterSettings 
    { NewLineHandling = NewLineHandling.None, Indent = true };
using (XmlWriter xmlWriter = XmlWriter.Create(filePath, xmlWriterSettings))
{
    xDoc.Save(xmlWriter);
    xmlWriter.Flush();
}

Чтобы прочитать XML-файл в XElement, сохранив \ r нетронутым:

using (XmlTextReader xmlTextReader = new XmlTextReader(filePath) 
   { WhitespaceHandling = WhitespaceHandling.Significant })
{
     xmlTextReader.MoveToContent();
     xDatabaseElement = XElement.Load(xmlTextReader);
}
person CMarsden    schedule 16.08.2011
comment
Спасибо за это, очень помогли мне, очень признательны! - person m.t.bennett; 27.02.2013
comment
Это связано с тем, что для XmlTextReader для параметра нормализации по умолчанию установлено значение false, в отличие от XmlReader.Create, который всегда нормализует символы новой строки, несмотря ни на что. См. msdn.microsoft. com / en-us / library / и примечание в конце msdn.microsoft.com/en-us/library/ - person David Burg; 21.04.2017

Решение 1. Напишите разрешенный XML

Используйте правильно настроенную опцию XmlWriter с NewLineHandling.Entitize, чтобы XmlReader не устранял нормализацию концов строк.

Вы можете использовать такой кастом XmlWriter даже с XDocument:

xDoc.Save(XmlWriter.Create(fileName, new XmlWriterSettings { NewLineHandling = NewLineHandling.Entitize }));

Решение 2. Читайте XML без права доступа без нормализации

Решение 1 - более чистый способ; однако возможно, что у вас уже есть XML без прав, и вы не можете изменить создание, но все же хотите предотвратить нормализацию. В принятом ответе предлагается заменить, но при этом все \ n вхождения заменяются вслепую, даже если это нежелательно. Чтобы получить все окончания строк в том виде, в котором они находятся в файле, вы можете попробовать использовать устаревший класс XmlTextReader, который по умолчанию не нормализует файлы XML. Вы также можете использовать его с XDocument:

var xDoc = XDocument.Load(new XmlTextReader(fileName));
person György Kőszeg    schedule 24.01.2017

Есть более быстрый способ, если вы просто пытаетесь перейти на UTF-8. Сначала создайте писателя:

public class EncodedStringWriter : StringWriter
{
    public EncodedStringWriter(StringBuilder sb, Encoding encoding)
        : base(sb)
    {
        _encoding = encoding;
    }

    private Encoding _encoding;

    public override Encoding Encoding
    {
        get
        {
            return _encoding;
        }
    }

}

Тогда используйте это:

XmlDocument doc = new XmlDocument();
doc.LoadXml("<foo><bar /></foo>");

StringBuilder sb = new StringBuilder();
XmlWriterSettings xws = new XmlWriterSettings();
xws.Indent = true;

using( EncodedStringWriter w = new EncodedStringWriter(sb, Encoding.UTF8) )
{
    using( XmlWriter writer = XmlWriter.Create(w, xws) )
    {
        doc.WriteTo(writer);
    }
}
string xml = sb.ToString();

Необходимо предоставить кредит, если он причитается.

person micahtan    schedule 25.11.2009

XmlReader читает файлы, а не записывает их. Если вы получаете \ n в вашем ридере, это потому, что это то, что находится в файле. И \ n, и \ r являются пробелами и семантически одинаковы в XML, это не повлияет на значение или содержание данных.

Редактировать:

Это похоже на C #, а не на Ruby. Как говорит бинарный кодировщик, ReadOuterXml определен для возврата нормализованного XML. Обычно это именно то, что вам нужно. Если вам нужен необработанный XML, вы должны использовать Encoding.UTF8.GetString(memStream.ToArray()), а не XmlReader.

person Dour High Arch    schedule 25.11.2009
comment
Мрачно, я добавил свой код. Если я использую XmlWriter с NewLineHandling = Replace, не следует ли писать правильную строку? - person user156144; 25.11.2009