Сортировка файла XML по нескольким атрибутам - PullRequest
1 голос
/ 05 июня 2010

Я хочу отсортировать XML-файл «свободной формы» по нескольким атрибутам (сначала по T, а затем по L). XML немного сложен и структурирован, как показано ниже:

<?xml version="1.0" encoding="utf-8"?>
<wb xmlns:cf="http://www.macromedia.com/2004/cfform" xmlns:a="urn:dummy">
  <a:form name="chart">
    <a:fieldset FIELD="a" FIELDNAME="FieldSet1">
      <a:select1 FIELDNUMBER="01" L="1" T="2" />
      <a:input FIELDNUMBER="02" INDEX="4" L="200" T="1" />
    </a:fieldset>
    <a:fieldset FIELD="b" FIELDNAME="FieldSet1">
      <a:select1 FIELDNUMBER="03" T="3" L="1" />
      <a:input FIELDNUMBER="04" INDEX="7" T="4" L="200" />
      <a:fieldset FIELD="c" FIELDNAME="FieldSet1">
        <a:input FIELDNUMBER="05" T="10" INDEX="6" L="400" />
        <a:input FIELDNUMBER="06" T="8" INDEX="8" L="200" />
      </a:fieldset>
    </a:fieldset>
    <a:input FIELDNUMBER="08" INDEX="3" L="3" T="5" />
    <a:input FIELDNUMBER="09" INDEX="2" L="2" T="5" />
  </a:form>
</wb>

PS:

  1. Корневым элементом является wb, и за ним всегда следует: form
  2. L и T всегда находятся в элементах, которые имеют тег в пространстве имен a, единственным исключением является: fieldset, в котором нет L и T
  3. a: fieldset может иметь несколько дочерних элементов пространства имен a, включая другой a: fieldset
  4. При сортировке дочерних элементов, находящихся в наборе полей, они должны оставаться привязанными к своему текущему родителю.

Полученный результат должен быть следующим:

<?xml version="1.0" encoding="utf-8"?>
<wb xmlns:cf="http://www.macromedia.com/2004/cfform" xmlns:a="urn:dummy">
  <a:form name="chart">
    <a:fieldset FIELD="a" FIELDNAME="FieldSet1">
      <a:input FIELDNUMBER="02" INDEX="4" L="200" T="1" />
      <a:select1 FIELDNUMBER="01" L="1" T="2" />
    </a:fieldset>
    <a:fieldset FIELD="b" FIELDNAME="FieldSet1">
      <a:select1 FIELDNUMBER="03" T="3" L="1" />
      <a:input FIELDNUMBER="04" INDEX="7" T="4" L="200" />
      <a:fieldset FIELD="c" FIELDNAME="FieldSet1">
        <a:input FIELDNUMBER="06" T="8" INDEX="8" L="200" />
        <a:input FIELDNUMBER="05" T="10" INDEX="6" L="400" />
      </a:fieldset>
    </a:fieldset>
    <a:input FIELDNUMBER="09" INDEX="2" L="2" T="5" />
    <a:input FIELDNUMBER="08" INDEX="3" L="3" T="5" />
  </a:form>
</wb>

Для лучшего понимания мы можем предположить, что L обозначает Left, а T обозначает Top. Итак, идея этого заключается в том, что когда я просматриваю преобразованный XML, я могу сразу заметить, какие элементы предшествуют чему.

Что вы думаете об этом?

1 Ответ

0 голосов
/ 24 июня 2010

попробуйте это: (внесите некоторые изменения, если я не правильно понял ваши вопросы)

<xsl:template match="/wb">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates mode="aaa" select="."/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*" mode="aaa">
    <xsl:if test="child::*[1][not(@T) or not(@L)]">
      <xsl:for-each select="child::*[not(@T) or not(@L)]">
        <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates mode="aaa" select="."/>
        </xsl:copy>
      </xsl:for-each>
    </xsl:if>
    <xsl:variable name="sorted1">
      <xsl:for-each select="a:*[@T and @L]">
        <xsl:sort select="@T" data-type="number" order="ascending"></xsl:sort>
        <xsl:copy>
          <xsl:copy-of select="@*"/>
        </xsl:copy>
      </xsl:for-each>
    </xsl:variable>
    <xsl:for-each select="msxsl:node-set($sorted1)/*[not(@T=preceding-sibling::*/@T)]">
      <xsl:variable name="tval" select="@T"/>
      <xsl:for-each select="msxsl:node-set($sorted1)/*[@T=$tval]">
        <xsl:sort select="@L" data-type="number" order="ascending"></xsl:sort>
        <xsl:copy>
          <xsl:copy-of select="@*"/>
        </xsl:copy>
      </xsl:for-each>
    </xsl:for-each>

    <xsl:if test="not(child::*[1][not(@T) or not(@L)])">
      <xsl:for-each select="child::*[not(@T) or not(@L)]">
        <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates mode="aaa" select="."/>
        </xsl:copy>
      </xsl:for-each>
    </xsl:if>

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