Как сохранить символы новой строки в атрибуте XML?

Мне нужно сохранить содержимое, содержащее символы новой строки, в некоторых атрибутах XML, а не в тексте. Метод должен быть выбран таким образом, чтобы я мог его декодировать в XSLT 1.0/ESXLT/XSLT 2.0

Каков наилучший метод кодирования?

Просьба предложить/дать некоторые идеи.

Ответ 1

В совместимом DOM API вам нечего делать. Просто сохраните фактические символы новой строки в атрибуте, API будет их кодировать правильно самостоятельно (см. Спецификация Canonical XML, раздел 5.2).

Если вы сделаете свою собственную кодировку (т.е. заменив \n на 
 перед сохранением значения атрибута), API снова закодирует ваш ввод, в результате получится 
 в файле XML.

Нижняя строка, строковое значение сохраняется дословно. Вы получаете то, что вы вложили, не нужно вмешиваться.

Однако... некоторые реализации не соответствуют требованиям. Например, они будут кодировать символы & в значениях атрибутов, но забывают о символах новой строки или вкладках. Это ставит вас в проигрышную позицию, так как вы не можете просто заменить символы новой строки 
 заранее.

Эти реализации сохраняют незашифрованные символы новой строки, например:

<xml attribute="line 1
line 2" />

После разбора такого документа литеральные символы новой строки в атрибутах нормализуются в одно пространство (опять же, в соответствии со спецификацией) - и, следовательно, они теряются.

Сохранение (и сохранение!) новых строк в атрибутах невозможно в этих реализациях.

Ответ 2

Вы можете использовать объект &#10; для представления новой строки в атрибуте XML. &#13; может использоваться для представления возврата каретки. Стиль CRLF в Windows можно представить как &#13;&#10;.

Это законный синтаксис XML. Подробнее см. Спецификация XML.

Ответ 3

Грубый ответ может быть:

XmlDocument xDoc = new XmlDocument();
xDoc.Load(@"Agenda.xml");
//make stuff with the xml
//make attributes value = "\r\n" (you need both expressions to make a new line)
string a = xDoc.InnerXml.Replace("&#xD;", "\r").Replace("&#xA;", "\n").Replace("><",">\r    \n<");
StreamWriter sDoc = new StreamWriter(@"Agenda.xml");
sDoc.Write(a);
sDoc.Flush();
sDoc.Dispose();

Это будет, как вы видите, просто строка

Ответ 4

Немного другой подход, который был полезен в некоторых situations-

Заполнители и Найти и заменить.

Перед синтаксическим анализом вы можете просто использовать свой собственный маркер/заполнитель переноса строки, затем во 2-й половине ситуации просто замените строку на любой эффективный символ перевода строки, будь то \n или или или # & 10; или \u2028 или любой из различных символов разрыва строки там. Найдите и замените их обратно после первоначальной установки собственного заполнителя в данных.

Это полезно, когда парсеры, такие как jQuery $.parseXML(), удаляют незашифрованные разрывы строк. Например, вы могли бы использовать {LBREAK} в качестве символа разрыва строки, вставить его во время необработанного текста и заменить его позже после анализа в объекте XML. String.replaceAll() - полезный прототип.

Итак, концепция грубого кода с jquery и прототипом replaceAll (этот код не тестировался, но он покажет концепцию):

function onXMLHandleLineBreaks(_result){
    var lineBreakCharacterThatGetsLost = '&#10;';
    var lineBreakCharacterThatGetsLost = '&#xD;';
    var rawXMLText = _result; // hold as text only until line breaks are ready
        rawXMLText = String(rawXMLText).replaceAll(lineBreakCharacterThatGetsLost, '{mylinebreakmarker}'); // placemark the linebreaks with a regex find and replace proto
    var xmlObj = $.parseXML(rawXML); // to xml obj
    $(xmlObj).html( String(xmlObj.html()).replaceAll('{mylinebreakmarker}'), lineBreakCharacterThatWorks ); // add back in line breaks
    console.log('xml with linebreaks that work: ' + xmlObj);
}

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