Получение брата с помощью xsl: key - PullRequest
1 голос
/ 13 марта 2012

У меня есть схема таблицы, в которой есть некоторые данные метаполя, которые мне нужно перенести на уровень строки.

Так что это ...

<tables>
    <table name="T01">
        <columns>
            <column name="F01">
                <heading>Field 1</heading>
            </column >
            <column name="F02">
                <heading>Field 2</heading>
            </column>
        </columns>
        <rows>
            <row>
                <field name="F01">AAAAA</field>
                <field name="F02">BBBBB</field>
            </row>
            <row>
                <field name="F01">DDDDD</field>
                <field name="F02">EEEEE</field>
            </row>
        </rows>
    </table>
    <table name="T02">
        <!-- ... -->
    </table>
</tables>

должно стать этим ...

<tables>
    <table name="T01">
        <rows>
            <row>
                <field name="F01">
                    <heading>Field 1</heading>
                    <value>AAAAA</value>
                </field>
                <field name="F02">                    
                    <heading>Field 2</heading>  
                    <value>BBBBB</value>
                </field>
            </row>
            <row>
                <field name="F01">
                    <heading>Field 1</heading>
                    <value>DDDDD</value>
                </field>
                <field name="F02">                    
                    <heading>Field 2</heading>  
                    <value>EEEEE</value>
                </field>
            </row>
        </rows>
    </table>
    <table name="T02">
        <!-- ... -->
    </table>
</tables>

Я уверен, что есть тонны простых способов сделать это с помощью XSLT, но из-за моего инструмента мне действительно нужно получить заголовок столбца с помощью ключа (),Так что-то вроде этого ...

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

  <!-- This won't work but if it did ... -->
  <xsl:key name="field-heading"
          match="../../columns/column/heading"
          use="../@name" />

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>


  <xsl:template match="field">
    <field name="{@name}">
      <heading>
        <xsl:value-of select="key('field-heading', @name)"/>
      </heading>
      <value>
        <xsl:value-of select="."/>
      </value>
    </field>
  </xsl:template>

  <xsl:template match="columns"/>

</xsl:stylesheet>

Но атрибут соответствия xsl: key не разрешает родительскую ось, и я не уверен, есть ли другие способы сделать его подходящим.

Ответы [ 3 ]

0 голосов
/ 13 марта 2012

Попробуйте использовать это:

<xsl:key name="field-heading"
    match="heading"
    use="parent::column/@name" />

В этом случае ../ не будет работать, поскольку путь use не начинается с корня.


РЕДАКТИРОВАТЬ

Попробуйте создать ключ, используя table/@name вместе с column/@name.Это должно сделать его уникальным.

XML Input (я надеюсь, что это представляет проблему из вашего комментария.)

<tables>
  <table name="T01">
    <columns>
      <column name="F01">
        <heading>Field 1</heading>
      </column>
      <column name="F02">
        <heading>Field 2</heading>
      </column>
    </columns>
    <rows>
      <row>
        <field name="F01">AAAAA</field>
        <field name="F02">BBBBB</field>
      </row>
      <row>
        <field name="F01">DDDDD</field>
        <field name="F02">EEEEE</field>
      </row>
    </rows>
  </table>
  <table name="T02">
    <columns>
      <column name="F01">
        <heading>Field A</heading>
      </column>
      <column name="F02">
        <heading>Field B</heading>
      </column>
    </columns>
    <rows>
      <row>
        <field name="F01">11111</field>
        <field name="F02">22222</field>
      </row>
      <row>
        <field name="F01">44444</field>
        <field name="F02">55555</field>
      </row>
    </rows>
  </table>
</tables>

Модифицированный XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <!-- This won't work but if it did ... -->
  <xsl:key name="field-heading"
    match="heading"
    use="concat(ancestor::table/@name,'+',parent::column/@name)" />

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="field">
    <field name="{@name}">
      <heading>
        <xsl:value-of select="key('field-heading', concat(ancestor::table/@name,'+',@name))"/>
      </heading>
      <value>
        <xsl:value-of select="."/>
      </value>
    </field>
  </xsl:template>

  <xsl:template match="columns"/>

</xsl:stylesheet>

Вывод XML

<tables>
  <table name="T01">

      <rows>
         <row>
            <field name="F01">
               <heading>Field 1</heading>
               <value>AAAAA</value>
            </field>
            <field name="F02">
               <heading>Field 2</heading>
               <value>BBBBB</value>
            </field>
         </row>
         <row>
            <field name="F01">
               <heading>Field 1</heading>
               <value>DDDDD</value>
            </field>
            <field name="F02">
               <heading>Field 2</heading>
               <value>EEEEE</value>
            </field>
         </row>
      </rows>
  </table>
  <table name="T02">

      <rows>
         <row>
            <field name="F01">
               <heading>Field A</heading>
               <value>11111</value>
            </field>
            <field name="F02">
               <heading>Field B</heading>
               <value>22222</value>
            </field>
         </row>
         <row>
            <field name="F01">
               <heading>Field A</heading>
               <value>44444</value>
            </field>
            <field name="F02">
               <heading>Field B</heading>
               <value>55555</value>
            </field>
         </row>
      </rows>
  </table>
</tables>
0 голосов
/ 14 марта 2012

Несколько более простое решение :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kColByNames" match="column" use=
  "concat(../../@name, '+', @name)"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="field">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <heading>
     <xsl:value-of select=
      "key('kColByNames', concat(ancestor::table[1]/@name, '+', @name))"/>
   </heading>
   <value><xsl:value-of select="."/></value>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="columns"/>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML :

<tables>
    <table name="T01">
        <columns>
            <column name="F01">
                <heading>Field 1</heading>
            </column>
            <column name="F02">
                <heading>Field 2</heading>
            </column>
        </columns>
        <rows>
            <row>
                <field name="F01">AAAAA</field>
                <field name="F02">BBBBB</field>
            </row>
            <row>
                <field name="F01">DDDDD</field>
                <field name="F02">EEEEE</field>
            </row>
        </rows>
    </table>
    <table name="T02">
        <!-- ... -->
    </table>
</tables>

желаемый, правильный результат получен :

<tables>
   <table name="T01">
      <rows>
         <row>
            <field name="F01">
               <heading>Field 1</heading>
               <value>AAAAA</value>
            </field>
            <field name="F02">
               <heading>Field 2</heading>
               <value>BBBBB</value>
            </field>
         </row>
         <row>
            <field name="F01">
               <heading>Field 1</heading>
               <value>DDDDD</value>
            </field>
            <field name="F02">
               <heading>Field 2</heading>
               <value>EEEEE</value>
            </field>
         </row>
      </rows>
   </table>
   <table name="T02"><!-- ... --></table>
</tables>

Объяснение : переопределение правила идентификации и использование составного ключа - column определяется пара его атрибута name и атрибут name его прародителя table.

0 голосов
/ 13 марта 2012

Основная проблема заключается в том, что контекстом для определения ключа является документ, а не место, где вы используете ключ, поэтому определение должно быть

<xsl:key name="field-heading"
    match="/tables/table/columns/column/heading"
    use="../@name" />

В вашем XML есть несколько опечаток - это то, что я думаю, должно быть

<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="C:/Users/morank/Documents/temp/code.xsl"?>
<tables>
    <table name="T01">
        <columns>
            <column name="F01">
                <heading>Field 1</heading>
            </column>
            <column name="F02">
                <heading>Field 2</heading>
            </column>
        </columns>
        <rows>
            <row>
                <field name="F01">AAAAA</field>
                <field name="F02">BBBBB</field>
            </row>
            <row>
                <field name="F01">DDDDD</field>
                <field name="F02">EEEEE</field>
            </row>
        </rows>
    </table>
    <table name="T02">
        <!-- ... -->
    </table>
</tables>

Применение следующего XSLT

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

    <!-- This won't work but if it did ... -->
    <xsl:key name="field-heading"
        match="/tables/table/columns/column/heading"
        use="../@name" />

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="field">
        <field name='{@name}'>
            <heading>
                <xsl:value-of select="key('field-heading', @name)"/>
            </heading>
            <value>
                <xsl:value-of select="."/>
            </value>
        </field>
    </xsl:template>

    <xsl:template match="columns"/>

</xsl:stylesheet>

Дает желаемый результат:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="C:/Users/morank/Documents/temp/code.xsl"?><tables>
    <table name="T01">        
        <rows>
            <row>
                <field name="F01">
                    <heading>Field 1</heading>
                    <value>AAAAA</value>
                </field>
                <field name="F02">
                    <heading>Field 2</heading>
                    <value>BBBBB</value>
                </field>
            </row>
            <row>
                <field name="F01">
                    <heading>Field 1</heading>
                    <value>DDDDD</value>
                </field>
                <field name="F02">
                    <heading>Field 2</heading>
                    <value>EEEEE</value>
                </field>
            </row>
        </rows>
    </table>
    <table name="T02">
        <!-- ... -->
    </table>
</tables>

Обратите внимание, что я также изменил шаблон на стандартное преобразование идентичности и убедился, что имя поля было скопировано

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