Отказ от ответственности: следующее является грехом против XML. Вот почему я пытаюсь изменить это с помощью XSLT :)
Мой XML в настоящее время выглядит так:
<root>
<object name = "blarg" property1 = "shablarg" property2 = "werg".../>
<object name = "yetanotherobject" .../>
</root>
Да, я помещаю все текстовые данные в атрибуты. Я надеюсь, что XSLT может меня спасти; Я хочу двигаться к чему-то вроде этого:
<root>
<object>
<name>blarg</name>
<property1>shablarg</name>
...
</object>
<object>
...
</object>
</root>
У меня на самом деле все это работает до сих пор, за исключением того, что мои грехи против XML были более ... исключительными. Некоторые теги выглядят так:
<object description = "This is the first line
This is the third line. That second line full of whitespace is meaningful"/>
Я использую xsltproc под Linux, но, похоже, у него нет никаких вариантов для сохранения пробелов. Я безуспешно пытался использовать xsl: preserve-space и xml: space = "preserve". Кажется, что каждый вариант, который я нашел, применим к сохранению пробелов внутри самих элементов, но не атрибутов. Каждый раз приведенное выше изменяется на:
This is the first line This is the third line. That second line full of whitespace is meaningful
Итак, вопрос в том, могу ли я сохранить пробел атрибута?
related: stackoverflow.com/questions/449627 - связанный: stackoverflow.com/questions/2004386 - связанный: stackoverflow.com/questions/1289524





Согласно Аннотированная спецификация XML, пробелы в значениях атрибутов нормализуются процессором XML (см. Аннотацию (T) к 3.3.3). Так что, похоже, ответ - нет.
если вы не можете управлять своим xml-процессором.
На самом деле это проблема необработанного синтаксического анализа XML, а не то, с чем XSLT может вам помочь. Синтаксический анализ XML должен преобразовывать символы новой строки в этом значении атрибута в пробелы в соответствии с «3.3.3 Нормализация значения атрибута» в стандарте XML. Таким образом, все, что в настоящее время читает ваши атрибуты описания и сохраняет символы новой строки, делает это неправильно.
Вы можете восстановить символы новой строки, предварительно обработав XML, чтобы экранировать символы новой строки на & # 10; ссылки на символы, если у вас также нет новых строк, в которых запрещены charref, например, внутри тела тега. Charref должны сохраняться как управляющие символы до значения атрибута, где вы затем можете превратить их в текстовые узлы.
Я не уверен, что это сработает. Charref заменяются байтами, которые они представляют, процессором XML, и поэтому charref, относящийся к пробельному символу (например, LINE FEED), будет нормализован как пробел.
Стандартный и DOM Test Suite говорят, что он работает; Ваша реализация может отличаться, но те, которые я тестировал, могут.
@ChuckB Я думаю, это зависит от можете ли вы управлять своим xml-процессором. Я могу создать хороший результат с .xsl, который работает как в saxon, так и в firefox.
Тот же самый раздел спецификации XML особо отмечает, что символьные ссылки, такие как 
Выполнять работу: «если ненормализованное значение атрибута содержит символьную ссылку на символ пробела, отличный от пробела (# x20), нормализованное значение содержит сам ссылочный символ». Конечно, на практике это будет работать только в совместимых реализациях ...
Как указывали другие, спецификация XML не позволяет сохранять пробелы в атрибутах. Фактически, это одно из немногих различий между тем, что вы можете делать с атрибутами и элементами (другой основной фактор заключается в том, что элементы могут содержать другие теги, а атрибуты - нет).
Вам придется сначала обработать файл вне XML, чтобы сохранить пробелы.
Я думаю, это заблуждение. Если вы можете управлять своим xml-процессором, само по себе кажется допустимым и возможным сохранить это пустое пространство. Я смог добиться результата.
Если вы можете управлять своим XML-процессором, вы можете это сделать.
Из моего другой ответ (с которым связано много ссылок):
если у вас есть XML, например
<?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>
<!DOCTYPE elemke [
<!ATTLIST brush wood CDATA #REQUIRED>
]>
<elemke>
<brush wood = "guy
threep"/>
</elemke>
и XSL вроде
<?xml version = "1.0" encoding = "UTF-8"?>
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:template name = "split">
<xsl:param name = "list" select = "''" />
<xsl:param name = "separator" select = "'
'" />
<xsl:if test = "not($list = '' or $separator = '')">
<xsl:variable name = "head" select = "substring-before(concat($list, $separator), $separator)" />
<xsl:variable name = "tail" select = "substring-after($list, $separator)" />
<xsl:value-of select = "$head"/>
<br/><xsl:text>
</xsl:text>
<xsl:call-template name = "split">
<xsl:with-param name = "list" select = "$tail" />
<xsl:with-param name = "separator" select = "$separator" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match = "brush">
<html>
<xsl:call-template name = "split">
<xsl:with-param name = "list" select = "@wood"/>
</xsl:call-template>
</html>
</xsl:template>
</xsl:stylesheet>
вы можете получить html, например:
<html>guy<br>
threep<br>
</html>
как проверено / произведено с процессором, подобным этой командной строке саксонский:
java -jar saxon9he.jar -s:in.xml -xsl:in.xsl -o:out.html
ATTLIST и DOCTYPE здесь фактически не нужны, CDATA будет здесь "типом атрибута" по умолчанию для этого AttValue.
К вашему сведению, случайный пост о процессоре против парсера: xygenxml.com/archives/xsl-list/200009/msg00750.html
Кредит Томалак для шаблона 'string', потому что в моем целевом xml-процессоре tokenize был недоступен.
Вы должны заменить ваши пробелы ссылками на сущности внутри значения атрибута, например, заменить
<object description = "first line\ nnext line"/>на<object description = "first line
next line"/>. Нормализация значения атрибута (3.3.3) затем зависит от типа атрибута, который я считаюCDATAпо умолчанию. Однако я думаю, что вы можете заставить это сделать это с помощью<!DOCTYPE root [ <!ATTLIST object description CDATA #IMPLIED>'>- может быть, верным, а может и нет. Затем, если у вас есть XSL, вам нужно убедиться, что вы обрабатываете пустое пространство вручную, я сделал то же, что иstring-join()иtokenize().