Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

Поиск узлов между двумя узлами с помощью XSLT. Как? (Hueker, оценка: 2)
Author Message
Hueker
Заглянувший



Joined: 08 Jan 2007
Posts: 14
Карма: -22
   поощрить/наказать


PostPosted: Thu May 19, 2011 11:32 pm (написано за 15 минут 12 секунд)
   Post subject: Поиск узлов между двумя узлами с помощью XSLT. Как?
Reply with quote

Здравствуйте!

Прошу помощи в решении следующей задачи: у меня есть XML документ, упрощенно для лучшего понимания задачи такой:
Code (xml): скопировать код в буфер обмена
<?xml version="1.0" encoding="utf-8"?>
<pricelist>
  <category>Категория 1</category>
  <vendor>Производитель 1.1.</vendor>
  <product>Продукт 1.1.1</product>
  <product>Продукт 1.1.2</product>
  <product>Продукт 1.1.3</product>
  <category>Категория 2</category>
  <product>Продукт 2.1</product>
  <vendor>Производитель 2.1</vendor>
  <product>Продукт 2.1.1</product>
  <product>Продукт 2.1.2</product>
</pricelist>
Нужно его преобразовать в древовидный вид, а именно такой:
Code (xml): скопировать код в буфер обмена
<?xml version="1.0" encoding="utf-8"?>
<pricelist>
  <category name=" 1">
    <vendor name=" 1.1.">
      <product></product>
      <product></product>
      <product></product>
    </vendor>
  </category>
  <category name=" 2">
    <vendor name="Unknown">
      <product></product>
    </vendor>
    <vendor name=" 2.1">
      <product></product>
      <product></product>
    </vendor>
  </category>
</pricelist>
Некоторые пояснения:
- продукты для которых не указан производитель попадают в специальный производитель с именем Unknown, такой Unknown производитель может быть только один в каждой категории.
- цифры у продуктов и производителей я добавил только для примера.
- вообще в прайсе все имена категорий уникальны.
- имена продуктов и производителей уникальны в пределах категории, но могут повторяться в пределах прайса.

Я только начал изучать XLST, написал пока такой .xsl файл (могут быть ошибки, т.к. я его переделал для этого упрощенного примера, но главное суть):
Code (xml): скопировать код в буфер обмена
<?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" version="1.0" encoding="utf-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="table">
      <pricelist>
      <xsl:apply-templates select="//category"/>
      </pricelist>
    </xsl:template>

    <xsl:template match="category">
      <xsl:variable name="category_name">
        <xsl:value-of select="child::text()"/>
      </xsl:variable>
      <category name="{$category_name}">
        <xsl:variable name="next_category"
                      select="(self::node()/following-sibling::category)[1]" />

        <xsl:variable name="current_category" select="self::node()"/>
<!--
Тут непонятно что писать...

Я нашел фрагмент со следующей страницы: http://www.biglist.com/lists/xsl-list/archives/200201/msg00659.html
  <xsl:copy-of select="following-sibling::*
                         [generate-id(following-sibling::comma[1]) =
                          generate-id($next-comma)]" />

Но как его использовать здесь непонятно...
--> 

      </category>
    </xsl:template>
</xsl:stylesheet>
Пояснения и вопрос еще я добавил в комментариях XML. После преобразования XML будет обработан PHP скриптом.

Прошу помощи именно по XML части. Как можно получить на выходе документ в нужном виде из исходного?
Back to top
View user's profile Send private message
Hueker
Заглянувший



Joined: 08 Jan 2007
Posts: 14
Карма: -22
   поощрить/наказать


PostPosted: Sat May 21, 2011 8:25 am (спустя 1 день 8 часов 52 минуты; написано за 36 секунд)
   Post subject:
Reply with quote

Решение было получено, благодаря человеку с ником ss, за что ему огромное спасибо!

Привожу решение:
Code (xml): скопировать код в буфер обмена
<?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" version="1.0" encoding="UTF-8" indent="yes"/>

  <xsl:template match="/">
     <pricelist>
        <xsl:apply-templates select="pricelist/category"/>
     </pricelist>
  </xsl:template>

  <xsl:template match="category">
     <xsl:apply-templates select="pricelist/category"/>
     <category name="{./text()}">
        <xsl:apply-templates select="current()[following-sibling::*[1][self::product]]" mode="unknown"/>

        <xsl:apply-templates select="." mode="vendors"/>
     </category>
  </xsl:template>

  <xsl:template match="*"/>

<!--//////////////////////////////////////////////////////////////////////////////-->

  <xsl:template match="category" mode="unknown">
     <vendor name="Unknown">
        <xsl:apply-templates select="following-sibling::*[1][self::product]" mode="products"/>
     </vendor>
  </xsl:template>

  <xsl:template match="*" mode="unknown"/>

<!--//////////////////////////////////////////////////////////////////////////////-->

  <xsl:template match="product" mode="products">
     <xsl:copy-of select="."/>

     <xsl:apply-templates select="following-sibling::*[1][self::product]" mode="products"/>
  </xsl:template>

  <xsl:template match="*" mode="products"/>

<!--//////////////////////////////////////////////////////////////////////////////-->

  <xsl:template match="vendor" mode="vendor">
     <vendor name="{./text()}">
        <xsl:apply-templates select="following-sibling::*[1][self::product]" mode="products"/>
     </vendor>
  </xsl:template>

  <xsl:template match="*" mode="vendor"/>

<!--//////////////////////////////////////////////////////////////////////////////-->

  <xsl:template match="category | vendor" mode="vendors">
     <xsl:apply-templates select="." mode="vendor"/>

     <xsl:variable name="first_vendor" select="following-sibling::vendor[1]"/>
     <xsl:variable name="next_category" select="following-sibling::category[1]"/>

     <xsl:apply-templates select="$first_vendor[not(. = $next_category/following-sibling::*)]" mode="vendors"/>
  </xsl:template>

  <xsl:template match="*" mode="vendors"/>

</xsl:stylesheet>
Вопрос решен, тему можно закрыть.
Back to top
View user's profile Send private message
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Sat May 21, 2011 2:05 pm (спустя 5 часов 39 минут; написано за 4 минуты 54 секунды)
   Post subject:
Reply with quote

Задача интересная. Если это полноценное готовое решение, то его стоит оставить в топе. Когда-то мне понадобилось конвертировать в xml/html-формат некий текстовый файл, содержащий иерархическую реестр-подобную структуру. В свое время решил нескольким десятков строк чистого кода без использования xslt.

Добавил 2 балла.
Back to top
View user's profile Send private message
bæv
Модератор «Дзена»



Joined: 27 Aug 2003
Posts: 7275
Карма: 9994
   поощрить/наказать


PostPosted: Mon Mar 26, 2012 2:53 pm (спустя 10 месяцев 5 дней 48 минут)
   Post subject:
Reply with quote


М

Ветка выделена в отдельную тему «спам»,
расположенную в форуме Мусоропровод (26 Марта 2012, 15:53).
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML