Как преобразовать значения атрибутов элементов и подэлементов xml в один новый элемент и подэлемент

Я безуспешно искал хорошую документацию, чтобы объяснить это. Это моя проблема:

это мои требования

  • корневому элементу необходимо изменить имя (это сделано),
  • Только одно имя атрибута в элементе второго уровня должно быть преобразовано в новый элемент.
  • Элемент второго уровня и остальные его атрибуты должны быть удалены
  • Все атрибуты в элементе третьего уровня (внутри элемента второго уровня) преобразуются в элемент второго уровня.
  • Элемент третьего уровня должен быть удален.

Текущий

<list>

<type name="drum" acustic="true" pieces="5" >
    <part name="pearl" id="0" version="0" displayOrder="0" customizationLevel="basic" />
    <part name="dw" id="1" version="0" displayOrder="0" customizationLevel="basic" />
</type>

<type name="guitar" acustic="true" pieces="1" >
    <part name="fender" id="0" version="0" displayOrder="0" customizationLevel="basic" />       
</type>

desired

<instrumentList>
    <instrument>
    <instrumentType>drum</instrumentType>
    <instrumentID>0</instrumentID>
    <instrumentBrand>pearl</instrumentBrand>
    <version>0</version>
    <displayOrder>0</displayOrder>
    <customizationLevel>basic</customizationLevel>
    </instrument>

    <intrument>
    <instrumentType>drum</instrumentType>
    <instrumentID>1</instrumentID>
    <instrumentBrand>dw</instrumentBrand>
    <version>0</version>
    <displayOrder>0</displayOrder>
    <customizationLevel>basic</customizationLevel>
    </instrument>
    <instrument>    
    <instrumentType>guitar</instrumentType>
    <instrumentID>0</instrumentID>
    <instrumentBrand>fender</instrumentBrand>
    <version>0</version>
    <displayOrder>0</displayOrder>
    <customizationLevel>basic</customizationLevel>
    </instrument>
</instrumentList>

Поэтому я безуспешно следовал следующему руководству и потокам Thread 1 Поток 2

Я могу сделать часть этого, но не все. Я уверен, что здесь есть что-то, чего я не понимаю, особенно с удалением элементов и созданием новых элементов и использованием некоторых атрибутов, а не всех. Даже если бы кто-то мог указать мне хорошую ссылку, где я могу понять, как xslt анализирует xml, чтобы у меня было лучшее представление, поскольку все примеры, которые я нашел, преобразуют каждый отдельный атрибут или элемент, и это, к сожалению, не мой случай.

Любая помощь будет принята с благодарностью


person user2441382    schedule 31.05.2013    source источник
comment
Пожалуйста, добавьте свой пример ввода и вывода xml. И выберите версию xlst xslt-1.0 или 2.0.   -  person hr_117    schedule 31.05.2013
comment
хорошо, я наконец-то смог добавить xml. Спасибо за помощь   -  person user2441382    schedule 01.06.2013
comment
Вы уверены, что instrument должен стать корневым элементом? Мне кажется странным.   -  person hr_117    schedule 01.06.2013
comment
на самом деле это не имеет значения, так как я не могу поместить настоящий xml, который я придумал. На самом деле важны изменения в иерархии, которые я только что нашел ссылка на сообщение, которое кажется похожим, но все же проще, чем это.   -  person user2441382    schedule 01.06.2013
comment
Ок, понял, почему ты так сказал. Вы правы. Инструмент не должен быть корневым элементом. Должен быть только контейнер инструментов, корень должен быть чем-то вроде instrimentList   -  person user2441382    schedule 03.06.2013


Ответы (1)


Ну, вы бы начали с общего шаблона, который превращал атрибуты в элементы, например:

<xsl:template match="@*">
   <xsl:element name="{local-name()}">
      <xsl:value-of select="."/>
   </xsl:element>
</xsl:template>

Но, глядя на ваши требования, некоторые атрибуты необходимо переименовать в элементы, и поэтому вы должны написать для них специальные шаблоны. Например, элемент @id выглядит так, как будто его нужно переименовать в InstrumentId.

<xsl:template match="@id">
   <instrumentID>
      <xsl:value-of select="."/>
   </instrumentID>
</xsl:template>

Единственная небольшая дополнительная работа, которую необходимо выполнить с шаблоном, соответствующим элементу part, заключается в том, что вам нужно вывести элемент instrumentType, значение которого равно родительскому атрибуту. Кроме того, вам просто нужно выбрать все элементы атрибута для преобразования

<xsl:template match="part">
   <instrumentType>
      <xsl:value-of select="../@name"/>
   </instrumentType>
   <xsl:apply-templates select="@*"/>
</xsl:template>

Для элемента type второго уровня вы можете разрешить его обработку встроенными шаблонами XSLT.

Попробуйте этот XSLT

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

   <xsl:template match="list">
      <instrument>
         <xsl:apply-templates/>
      </instrument>
   </xsl:template>

   <xsl:template match="part">
      <instrumentType>
         <xsl:value-of select="../@name"/>
      </instrumentType>
      <xsl:apply-templates select="@*"/>
   </xsl:template>

   <xsl:template match="@id">
      <instrumentID>
         <xsl:value-of select="."/>
      </instrumentID>
   </xsl:template>

   <xsl:template match="@name">
      <instrumentBrand>
         <xsl:value-of select="."/>
      </instrumentBrand>
   </xsl:template>

   <xsl:template match="@*">
      <xsl:element name="{local-name()}">
         <xsl:value-of select="."/>
      </xsl:element>
   </xsl:template>
</xsl:stylesheet>

При применении к вашему XML (при условии наличия закрывающего тега list) выводится следующее

<instrument>
   <instrumentType>drum</instrumentType>
   <instrumentBrand>pearl</instrumentBrand>
   <instrumentID>0</instrumentID>
   <version>0</version>
   <displayOrder>0</displayOrder>
   <customizationLevel>basic</customizationLevel>

   <instrumentType>drum</instrumentType>
   <instrumentBrand>dw</instrumentBrand>
   <instrumentID>1</instrumentID>
   <version>0</version>
   <displayOrder>0</displayOrder>
   <customizationLevel>basic</customizationLevel>

   <instrumentType>guitar</instrumentType>
   <instrumentBrand>fender</instrumentBrand>
   <instrumentID>0</instrumentID>
   <version>0</version>
   <displayOrder>0</displayOrder>
   <customizationLevel>basic</customizationLevel>
</instrument>
person Tim C    schedule 31.05.2013
comment
ну это намного лучше, чем я думал. Миллиард благодарностей и еще один вопрос, так как мне, вероятно, придется продолжать делать эти преобразования xslt, не могли бы вы дать мне ссылку на книгу или ссылку, где можно подробно изучить этот материал. Большинство уроков, которым я следовал, пропускают слишком много материала. (+1 за фантастический ответ) - person user2441382; 01.06.2013
comment
Взгляните на stackoverflow.com/questions/1858345/, который содержит несколько ссылок и книг. Некоторые книги написаны Майклом Кеем, очень активным в StackOverflow. - person Tim C; 01.06.2013