Преобразование файлов XML для редактирования и управления человеком с помощью VCS - PullRequest
1 голос
/ 01 июля 2010

Иногда файлы 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 в какой-либо унифицированный формат (например, сортирует (если порядок элементов не имеет значения)и объединяет пробелы) и где я могу указать, какие элементы должны быть однострочными?

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

Ответы [ 3 ]

1 голос
/ 01 июля 2010

Я не тестировал в каждом процессоре 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 может отличаться. Если дело обстоит именно так, сохраните логику и сериализуйте как TEXT (Вы должны смоделировать сериализацию XML путем вывода открывающих и закрывающих тегов, а также атрибутов)

Редактировать : Незначительные изменения для правильной сортировки различных сериализованных входных данных.

0 голосов
/ 01 июля 2010

Создал свой собственный сортировочный индекс на основе 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 -->
<!-- /3321482/preobrazovanie-failov-xml-dlya-redaktirovaniya-i-upravleniya-chelovekom-s-pomoschy-vcs -->

<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 голосов
/ 01 июля 2010

Да, есть XML-принтеры;Я всегда использую xmllint сам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...