2010-07-01 5 views
1

Иногда файлы XML необходимо хранить в некоторых VCS. Такие файлы часто редактируются с использованием инструментов графического интерфейса пользователя, которые могут изменять порядок элементов каждый раз по своему усмотрению.Преобразование XML-файлов в редактируемые и управляемые человеком VCS

Также VCS объединение, как правило, линия-ориентированный, и часто XML-файлы либо выглядит любит одну длинную линию или полностью отступом как

<foo> 
    <bar> 
     <name> 
      n3 
     </name> 
     <value> 
      qqq3 
     </value> 
    </bar> 
    <bar> 
     <name> 
      n2 
     </name> 
     <value> 
      qqq2 
     </value> 
    </bar> 
</foo> 

, в то время как они должны выглядеть

<foo> 
    <bar> <name> n2 </name> <value> qqq2 </value> </bar> 
    <bar> <name> n3 </name> <value> qqq3 </value> </bar> 
</foo> 

(например, " частично отступом "), чтобы быть более читабельными/редактируемыми, компактными. Одна простая логическая единица должна занимать одну строку.

Даже если кто-то преобразует XML-файл в такой красивый формат, кто-то другой отредактирует его в инструменте графического интерфейса, который будет изменять порядок и повторно использовать все, и это будет плохо (нечитабельно, и VCS сообщит о значительных изменениях, несмотря на то,).

Есть ли готовое преобразование XSLT (или другая программа), которое преобразует все файлы XML в какой-либо унифицированный формат (например, сортировки (если порядок элементов не имеет значения) и унифицирует пробелы), и где я могу указать, какие элементы должны быть oneliners?

Например, если я могу указать такое преобразование как фильтр в .gitattributes, и git автоматически обработает это.

ответ

0

Создал мой собственный индентор сортировки на основе http://www.dpawson.co.uk/xsl/sect2/pretty.html и ответа Алехандро: http://vi-server.org/vi/sortindent.xsl. Зеркальный здесь:

<!-- Change 'oneliner' to the name of element you want to see as one line --> 
<!-- Remove 'xsl:sort' element if you don't want sorting --> 
<!-- http://stackoverflow.com/questions/3157658/converting-xml-files-to-be-human-editable-and-managable-by-vcs/3160818#3160818 --> 

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml"/> 
    <xsl:param name="indent-increment" select="' '" /> 

    <xsl:template match="*"> 
     <xsl:param name="skip_indent" select="name()='oneliner' or name()='another_oneliner'"/> 
     <xsl:param name="indent" select="'&#xA;'"/> 

     <xsl:if test="not($skip_indent)"> 
     <xsl:value-of select="$indent"/> 

     <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates> 
     <xsl:with-param name="indent" select="concat($indent, $indent-increment)"/> 
     <xsl:sort select="@*|node()"/> 
     </xsl:apply-templates> 
     <xsl:if test="*"> 
      <xsl:value-of select="$indent"/> 
     </xsl:if> 

     </xsl:copy> 

     </xsl:if> 
     <xsl:if test="$skip_indent"> 
     <xsl:value-of select="$indent"/> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates> 
      <xsl:with-param name="indent" select="' '"/> 
      <xsl:with-param name="skip_indent" select="1"/> 
      <xsl:sort select="@*|node()"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
     </xsl:if> 
    </xsl:template> 

    <xsl:template match="comment()|processing-instruction()"> 
     <xsl:copy /> 
    </xsl:template> 

    <xsl:template match="text()"> 
     <xsl:param name="skip_indent" select="0"/> 
     <xsl:if test="$skip_indent"> 
      <xsl:value-of select="normalize-space(.)"/> 
     </xsl:if> 
     <xsl:if test="not($skip_indent)"> 
      <xsl:if test="not(normalize-space(.)='')"> 
       <xsl:value-of select="."/> 
      </xsl:if> 
     </xsl:if> 
    </xsl:template> 


</xsl:stylesheet> 

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

+0

@Vi: Я не верю в общие решения ... Кроме того, предположим следующее изменение вашего входного документа: ' n2'. Выполните свою трансформацию и скажите мне, является ли это желаемым результатом. – 2010-07-01 19:32:57

+0

@Alejandro, Если удалить сортировку, это будет просто индентор с возможностью «отключаться» отступов для некоторых элементов. Сортировка может быть изменена. Есть уже ' n2', не знаю, что менять. –

+1

@Vi: Я имел в виду, что вы должны попытаться изменить свой входной документ, чтобы проверить свою таблицу стилей. Например: нормализовать пространство в текстовом узле второго элемента 'name' и снова запустить таблицу стилей. Выдает ли он желаемый результат? – 2010-07-02 03:27:01

0

Да, есть XML prettyprinters; Я всегда использую xmllint.

+0

Я также иногда использую 'xmllint --format', но 1. Я не могу настроить отступы. 2. Он просто сохраняет пробелы в текстовых узлах, 3. Нет сортировки. –

+0

Ну, он не знает, что он может сортироваться так, чтобы это не удивительно. Очевидно, вам нужен форматтер, характерный для используемой схемы. Для этого я, вероятно, написал бы Perl-скрипт на основе XML :: LibXML2 (интерфейс к библиотеке за xmllint), но вы можете в принципе использовать что угодно. – reinierpost

+0

Уже реализовано в xslt. –

1

я не проверял в каждый XSLT процессор (На самом деле, я только проверил это в MSXSL):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes"/> 
    <xsl:template match="@*|node()" name="identity"> 
     <xsl:if test="self::bar"> 
      <xsl:text>&#xA;</xsl:text> 
     </xsl:if> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"> 
      <xsl:sort select="normalize-space(name)"/> 
      </xsl:apply-templates> 
      <xsl:if test="self::foo"> 
       <xsl:text>&#xA;</xsl:text> 
      </xsl:if> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="text()"> 
     <xsl:value-of select="normalize-space(.)"/> 
    </xsl:template> 
</xsl:stylesheet> 

Результат:

<foo> 
<bar><name>n2</name><value>qqq2</value></bar> 
<bar><name>n3</name><value>qqq3</value></bar> 
</foo> 

Примечание: XML сериализации может отличаться. Если это так, сохранить логику и сериализовать как текст (вы должны имитировать XML сериализацию по выходным открывающих и закрывающих теги, а также атрибуты)

Edit: Незначительные изменения для того, чтобы правильно сортировать Diferent serializated входа.

+0

Спасибо, я написал больше usiversal XSLT, основанный на ваших частях. –

Смежные вопросы