Изменение значения атрибута с помощью xslt

Есть ряд других вопросов, связанных с этой областью, но я не могу заставить их работать.

У меня есть преобразование, которое разбивает файл bean-компонента Spring, содержащий несколько bean-компонентов, на набор файлов, каждый из которых содержит один bean-компонент.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/beans/bean" xml:space="preserve"> 
            <xsl:result-document href='{translate(normalize-space(./property[@name="name"])," ", "_")}.xml'
            doctype-public="-//SPRING//DTD BEAN//EN"
            doctype-system="http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <xsl:copy-of select="."/>
</beans>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>

Это отлично работает, создавая файлы, которые начинаются так:

<!DOCTYPE beans
  PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean class="com.class.mine.Policy" name="bean1">
        <property name="name">

Чтобы файл выглядел идентично файлу, изначально созданному только с одним bean-компонентом (поскольку файл будет проверен в управлении исходным кодом, мне нужны только реальные различия), я хочу изменить атрибут name="beanN" на name="bean0" в каждом файле. Обратите внимание, что обычно тег bean-компонента может содержать дополнительные атрибуты, а также атрибуты class и name.

Ничто из того, что я пробовал на основе других ответов, здесь не работает. В основном я получаю сообщения об ошибках «Невозможно создать узел атрибута, родительским элементом которого является узел документа» и «Невозможно создать узел атрибута после создания дочернего элемента содержащего элемента».

Так что я упускаю что-то очевидное. Что мне нужно добавить, чтобы внести это дополнительное изменение?

Обновление: проблема частично связана с xml:space="preserve". Это предположительно вызывает создание текстовых узлов. Когда это удалено, я не так часто получаю ошибки, но я все еще не могу правильно преобразовать

(и на выходе есть

<beans><bean>

Как сделать перевод строки между этими тегами? Я могу использовать indent="yes" для форматирования вывода, но я действительно хочу сохранить исходный формат ввода, внося изменения только там, где мне нужно)

Обновление: одна из моих многочисленных попыток. Этот работает, но в основном представляет собой преобразование личности. result-doc закомментирован, чтобы упростить отладку. Я действительно не совсем понимаю, как работает xsl:attribute, поэтому достойное объяснение может помочь.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="beans/bean"> 
<!--             <xsl:result-document href='{translate(normalize-space(./property[@name="name"])," /", "_+")}.xml'
            doctype-public="-//SPRING//DTD BEAN//EN"
            doctype-system="http://www.springframework.org/dtd/spring-beans.dtd"
            omit-xml-declaration="no"> -->
<beans>
<xsl:apply-templates select="bean"/>
<xsl:copy-of select="." /> 
</beans>
<!-- </xsl:result-document> -->
</xsl:template>
 <xsl:template match="bean/@*">
      <xsl:copy>
          <xsl:attribute name="name">myvalue</xsl:attribute>
           <xsl:copy-of select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

person The Archetypal Paul    schedule 21.11.2013    source источник
comment
Вопрос: Почему вы считаете, что вам нужен перевод строки между тегами? Как вы думаете, имеет ли какое-то значение система XML?   -  person Kevin Brown    schedule 22.11.2013
comment
Для XML это не имеет значения. Это имеет значение, потому что эти конфигурации должны быть проверены в CVS, а CVS недостаточно умен, чтобы знать, что различия в пробелах несущественны в XML. Я не хочу, чтобы дополнительные ревизии CVS создавались для файлов, которые на самом деле одинаковы, т. е. я хочу получить то же форматирование, что и у менее ленивых разработчиков, которые экспортировали файлы один за другим.   -  person The Archetypal Paul    schedule 22.11.2013
comment
Ответ зависит от того, как именно вы пытались изменить значение атрибута элемента bean. Можете ли вы опубликовать фрагмент этого?   -  person Mathias Müller    schedule 22.11.2013
comment
Я могу, но, как я уже сказал, пока не все работает, поэтому я не уверен, насколько этот фрагмент поможет!   -  person The Archetypal Paul    schedule 22.11.2013
comment
Спасибо. Что касается проблемы с атрибутами, то, что вы пробовали, невозможно в XSLT, поэтому у вас есть эти ошибки. См. Ответ @Ians, чтобы узнать, как это сделать правильно.   -  person Mathias Müller    schedule 22.11.2013
comment
ХОРОШО. В каком-то смысле утешительно знать, что это невозможно!   -  person The Archetypal Paul    schedule 22.11.2013


Ответы (1)


Если вам нужен определенный отступ, вам придется самостоятельно вставить соответствующие переводы строк и пробелы:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <xsl:apply-templates select="beans/bean" />
  </xsl:template>

  <xsl:template match="bean"> 
    <xsl:result-document href='{translate(normalize-space(./property[@name="name"])," /", "_+")}.xml'
            doctype-public="-//SPRING//DTD BEAN//EN"
            doctype-system="http://www.springframework.org/dtd/spring-beans.dtd"
            omit-xml-declaration="no">
      <xsl:text>&#10;</xsl:text><!-- newline after the DOCTYPE -->
      <beans>
        <xsl:text>&#10;    </xsl:text><!-- newline and four spaces -->
        <bean>
          <xsl:copy-of select="@*" />
          <xsl:attribute name="name">bean0</xsl:attribute>
          <xsl:copy-of select="node()" />
        </bean>
        <xsl:text>&#10;</xsl:text><!-- newline between </bean> and </beans> -->
      </beans>
    </xsl:result-document>
  </xsl:template>
</xsl:stylesheet>

Для переименования:

        <bean>
          <xsl:copy-of select="@*" />
          <xsl:attribute name="name">bean0</xsl:attribute>
          <xsl:copy-of select="node()" />
        </bean>

сначала я копирую все атрибуты (возможно, включая name) из исходного тега bean, затем создаю (другой) атрибут name, который переопределит тот, который был скопирован, затем, наконец, копирую все дочерние узлы исходного элемента bean (который включает элементы , комментарии и текстовые узлы, так что сохранится исходный отступ).

person Ian Roberts    schedule 22.11.2013
comment
Спасибо. Выглядит в точку. Я до сих пор не очень понимаю, как копия атрибутов, а затем работа xsl:attribute - кажется, что копирование (или определение) атрибутов помещается в родительский узел? Но это работает! - person The Archetypal Paul; 22.11.2013
comment
ааааа Попробовал на тестовом примере, все работает. Запустил его на другом примере, и все файлы имеют узел компонента (и дочерние элементы) в одной строке :( хотя в исходном коде они находятся на нескольких строках/с отступом. Есть идеи? - person The Archetypal Paul; 22.11.2013
comment
Ладно, паникуй, это саксонская особенность. Я тестировал без ссылки на DTD (поскольку я не могу понять, как заставить Saxon использовать прокси-сервер при запуске из Eclipse), но позже я запускал с DTD (и вне корпоративной VPN) - Saxon услужливо делает что-то другое, если есть является DTD По умолчанию, если имеется DTD или схема, игнорируемые пробелы удаляются из любого исходного документа, загруженного из StreamSource или SAXSource. К счастью, это можно изменить. (stripWhitespace=нет) - person The Archetypal Paul; 22.11.2013
comment
@Paul, независимо от того, игнорируется ли конкретный бит пробела, определяется DTD - если у вас нет DTD, то по определению не существует игнорируемых пробелов. - person Ian Roberts; 22.11.2013
comment
Спасибо. Я просто не ожидал, что наличие или отсутствие DTD повлияет на пробелы. В справке Saxon не говорится, что это функция DTD, скорее предполагается, что это функция Saxon. Впрочем, теперь я знаю об этом, нет проблем - person The Archetypal Paul; 22.11.2013
comment
Ах, фу. Я установил stripWhitespace=none в Eclipse, но это не имеет никакого эффекта. Когда я указываю DTD, Saxon по-прежнему удаляет пробелы. Любые идеи? - person The Archetypal Paul; 23.11.2013
comment
использовать приложение, поддерживающее xml - person Kevin Brown; 23.11.2013
comment
@Paul Пол, есть ли причина, по которой вы должны использовать DTD (эры Spring 1.x) для проверки, а не механизм схемы, который рекомендуется с весны 2.0? - person Ian Roberts; 23.11.2013
comment
@Paul, как именно вы установили stripWhitespace=none в Eclipse? Если вы используете интерфейс javax.xml.transform для Saxon, то ключ, который вам нужно передать setAttribute, — это URI http://saxon.sf.net/feature/strip-whitespace. - person Ian Roberts; 23.11.2013
comment
@KevinBrown, если бы я мог, я бы сделал это. Это CVS, поэтому не вариант - person The Archetypal Paul; 23.11.2013
comment
@IanRoberts, для DTD и схемы, действительно вопрос для нашей команды разработчиков, но обратная и прямая совместимость в течение 5 с лишним лет различных версий, вероятно, является частью ответа. На полосе белого цвета я задал его в Run Configuration/Transform Parameters. Нет очевидного способа напрямую передать параметры каким-либо другим способом. - person The Archetypal Paul; 23.11.2013
comment
@Paul Я не знаю, какой плагин вы используете в Eclipse для запуска своих таблиц стилей, но параметры преобразования звучат для меня как место для передачи значений, к которым таблица стилей будет обращаться через элементы <xsl:param> верхнего уровня, а не место для настроить атрибуты самого преобразователя. - person Ian Roberts; 23.11.2013
comment
@Paul, попробуйте запустить его из командной строки — загрузите обычный дистрибутив Saxon HE с saxon.sf.net, и вы может работать java -jar saxon9he.jar -xsl:yourStylesheet.xsl -strip:none inputfile.xml - person Ian Roberts; 23.11.2013
comment
Хорошо, звучит разумное объяснение. Как-нибудь попробую через командную строку. Уже скачал Saxon, так как он не является стандартным с плагином Eclipse. - person The Archetypal Paul; 23.11.2013