Модераторы: diadiavova

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Можно ли сделать такое преобразование? 
V
    Опции темы
Mephisto
Дата 10.7.2010, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Волкъ
***


Профиль
Группа: Завсегдатай
Сообщений: 1818
Регистрация: 27.8.2003
Где: Питер

Репутация: нет
Всего: 34



Люди, можно ли при помощи xslt сделать такое преобразование. Сложность состоит в одном поле :(
Первый XML не мой, мне нужно получить второй.
Код

<?xml version="1.0"?>
<items>
  <item>
    <title>blah-blah-blah</title>
    <group>first. some test</group>
  </item>
  <item>
    <title>blah-blah-blah</title>
    <group>first. some second test</group>
  </item>
  <item>
    <title>blah-blah-blah</title>
    <group>second. tratata</group>
  </item>
  <item>
    <title>blah-blah-blah</title>
    <group>second. some second tratata</group>
  </item>
  <item>
    <title>second blah-blah-blah</title>
    <group>second. some second tratata</group>
  </item>
</items>


нужно получить вот это:
Код

<?xml version="1.0"?>
<groups>
  <group name="first">
    <elements name="some test">
      <element>blah-blah-blah</element>
    </elements>
    <elements name="some second test">
      <element>blah-blah-blah</element>
    </elements>
  </group>
  <group name="second">
    <elements name="tratata">
      <element>blah-blah-blah</element>
    </elements>
    <elements name="some second tratata">
      <element>blah-blah-blah</element>
      <element>second blah-blah-blah</element>
    </elements>
  </group>
</groups>

PM   Вверх
diadiavova
Дата 10.7.2010, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 22
Всего: 142



А в чём именно затруднение?


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Mephisto
Дата 10.7.2010, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Волкъ
***


Профиль
Группа: Завсегдатай
Сообщений: 1818
Регистрация: 27.8.2003
Где: Питер

Репутация: нет
Всего: 34



распарсить вот эту строку:
Код

<group>second. some second tratata</group>

И сделать тег:
Код

<group name="second">

и
Код

<elements name="some second tratata">


Добавлено через 35 секунд
И сгрупировать по ним как это в примере.
PM   Вверх
diadiavova
Дата 10.7.2010, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 22
Всего: 142



Цитата(Mephisto @  10.7.2010,  13:17 Найти цитируемый пост)
распарсить вот эту строку:

Здесь помогут строковые функции XPath
http://msdn.microsoft.com/ru-ru/library/ms256180.aspx
в частности substring-before и substring-after
Что-то в этом роде
Код

  <xsl:template match="item">
     <elements name="{normalize-space(substring-after(./group, '.'))}">
        <!--здесь вставляй содержимое-->
      </elements>     
  </xsl:template>

Что касается сгруппировать, то сложность зависит от того, является ли возможное количество групп конечным, если да, то тогда можно примерно так сделать
Код

  <xsl:template match="items">
    <group name="first">
      <xsl:apply-templates select="item[substring-before(./group, '.') = 'first']"/>
    </group>
    <group name="second">
      <xsl:apply-templates select="item[substring-before(./group, '.') = 'second']"/>
    </group>
  </xsl:template>

Если групп немного ессно, а если неизвестно какие группы могут быть, то будет сложнее smile , но тоже возможно

Код ни на чём не проверял - не для копипасты.

Это сообщение отредактировал(а) diadiavova - 10.7.2010, 14:11


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Mephisto
Дата 10.7.2010, 17:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Волкъ
***


Профиль
Группа: Завсегдатай
Сообщений: 1818
Регистрация: 27.8.2003
Где: Питер

Репутация: нет
Всего: 34



diadiavova, нет, количество групп заранее неизвестно. 
PM   Вверх
diadiavova
Дата 10.7.2010, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 22
Всего: 142



Ну сопсно выделить группы можно и так
Код

<?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"/>
  <xsl:template match="/">
      <xsl:apply-templates/>
  </xsl:template>
  <xsl:template match="items">
    <groups>
      <xsl:apply-templates select="//group"/>
    </groups>
  </xsl:template>
  <xsl:template match="group">
    <xsl:variable name="isfirst">
      <xsl:call-template name="isfirst">
        <xsl:with-param name="testnode" select=".."/>
        <xsl:with-param name="nodes" select="../preceding-sibling::item"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:if test="$isfirst = 'true'">
    <group name="{substring-before(text(),'.')}">
      <xsl:apply-templates select="//item"/>
    </group>
    </xsl:if>
  </xsl:template>
  <xsl:template match="item">
    <elements>
      
    </elements>
  </xsl:template>
  <xsl:template name="isfirst">
    <xsl:param name="testnode"/>
    <xsl:param name="nodes"/>
    <xsl:variable name="resulttext">
    <xsl:for-each select="$nodes">
      <xsl:if test="substring-before(./group/text(),'.') = substring-before($testnode/group/text(),'.')">#</xsl:if>
    </xsl:for-each>
    </xsl:variable>
    <xsl:value-of select="string-length($resulttext) = 0"/>
  </xsl:template>
</xsl:stylesheet>
дальше действовать по тому же принципу, но это гемор. Лучше выполнить двойное преобразование, или использовать расширения формата(если доступны ессно).


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
magelan
Дата 13.7.2010, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


потерял xPath
**


Профиль
Группа: Участник
Сообщений: 393
Регистрация: 5.4.2010

Репутация: 7
Всего: 16



Ключи - наше все...

Код

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

    <xsl:key name="g" match="/items/item/group" use="substring-before(text(), '.')" />

    <xsl:template match="/">
        <xsl:variable name="groups" select="/items/item/group" />
        <groups>
            <xsl:for-each select="$groups[generate-id()=generate-id(key('g',substring-before(text(), '.')))]">
                <xsl:variable name="name" select="substring-before(text(), '.')" />
                <group name="{$name}">
                    <xsl:for-each select="$groups[starts-with(text(), $name)]">
                        <elements name="{normalize-space(substring-after(text(), '.'))}">
                            <xsl:for-each select="../title">
                              <element>
                                <xsl:value-of select="text()" />
                              </element>
                            </xsl:for-each>
                        </elements>
                    </xsl:for-each>
                </group>
            </xsl:for-each>
        </groups>
    </xsl:template>
</xsl:stylesheet>


Это сообщение отредактировал(а) magelan - 13.7.2010, 17:05
PM MAIL   Вверх
Mephisto
Дата 13.7.2010, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Волкъ
***


Профиль
Группа: Завсегдатай
Сообщений: 1818
Регистрация: 27.8.2003
Где: Питер

Репутация: нет
Всего: 34



magelan, спасибо, идея понятна. Осталось только сгруппировать еще и элементы как в примере.
Такое преобразование дает результат:
Код

<?xml version="1.0" encoding="UTF-8"?>
<groups>
    <group name="first">
        <elements name="some test">
            <element>blah-blah-blah</element>
        </elements>
        <elements name="some second test">
            <element>blah-blah-blah</element>
        </elements>
    </group>
    <group name="second">
        <elements name="tratata">
            <element>blah-blah-blah</element>
        </elements>
        <elements name="some second tratata">
            <element>blah-blah-blah</element>
        </elements>
        <elements name="some second tratata">
            <element>second blah-blah-blah</element>
        </elements>
    </group>
</groups>

мне нужно:
Код

<?xml version="1.0"?>
<groups>
  <group name="first">
    <elements name="some test">
      <element>blah-blah-blah</element>
    </elements>
    <elements name="some second test">
      <element>blah-blah-blah</element>
    </elements>
  </group>
  <group name="second">
    <elements name="tratata">
      <element>blah-blah-blah</element>
    </elements>
    <elements name="some second tratata">
      <element>blah-blah-blah</element>
      <element>second blah-blah-blah</element>
    </elements>
  </group>
</groups>

PM   Вверх
Mephisto
Дата 14.7.2010, 00:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Волкъ
***


Профиль
Группа: Завсегдатай
Сообщений: 1818
Регистрация: 27.8.2003
Где: Питер

Репутация: нет
Всего: 34



magelan, то что я наваял можно как-то упростить, или нормально?
Код

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" />
    <xsl:key name="g" match="/items/item/group" use="substring-before(text(), '.')" />
    <xsl:key name="e" match="/items/item/group" use="normalize-space(substring-after(text(), '.'))" />
    <xsl:template match="/">
        <xsl:variable name="groups" select="/items/item/group" />
        <groups>
            <xsl:for-each select="$groups[generate-id()=generate-id(key('g',substring-before(text(), '.')))]">
                <xsl:variable name="name" select="substring-before(text(), '.')" />
                <group name="{$name}">
                 <xsl:variable name="elems" select="$groups[starts-with(text(), $name)]"/>
                    <xsl:for-each select="$elems[generate-id()=generate-id(key('e', normalize-space(substring-after(text(), '.'))))]">
                        <elements name="{normalize-space(substring-after(text(), '.'))}">
                            <xsl:for-each select="key('e', normalize-space(substring-after(text(), '.')))">
                              <element>
                                <xsl:value-of select="../title" />
                              </element>
                            </xsl:for-each>
                        </elements>
                    </xsl:for-each>
                </group>
            </xsl:for-each>
        </groups>
    </xsl:template>
</xsl:stylesheet>

мне вот эта строчка не дает покоя, не совсем понимаю что происходит:
Код

<xsl:for-each select="$groups[generate-id()=generate-id(key('g',substring-before(text(), '.')))]">

Ты выбираешь из множества узлов generate-id()=generate-id( что означает? 
key('g',substring-before(text(), '.') дает само по себе множество узлов насколько я понимаю.

Добавлено через 2 минуты и 43 секунды
С key я понял:
Код

<xsl:for-each select="key('cdlist', 'Empire Burlesque')">
  <p>
  Title: <xsl:value-of select="title" />
  <br />
  Artist: <xsl:value-of select="artist" />
  <br />
  Price: <xsl:value-of select="price" />
  </p>
</xsl:for-each>

А вот как работает подстановка множества в generate-id() не совсем
PM   Вверх
magelan
Дата 15.7.2010, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


потерял xPath
**


Профиль
Группа: Участник
Сообщений: 393
Регистрация: 5.4.2010

Репутация: 7
Всего: 16



ключи - это способ групировать.
цикл идет по группам и получает их только один раз

условие:
generate-id()=generate-id( key('g',substring-before(text(), '.')

позволяет выбрать ключевые группы, т.е. когда в цикл попадет группа
<group>first. some second test</group>
она будет проигнорированна, т.к. сгенерирует идентификатор не такой же, как и у группы
<group>first. some test</group>

теперь с элементами, спешил, плохо вчитался, поступаем как-то так:
Код

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

    <xsl:key name="g" match="/items/item/group" use="substring-before(text(), '.')" />
    <xsl:key name="g1" match="/items/item/group" use="text()" />

    <xsl:template match="/">
        <xsl:variable name="groups" select="/items/item/group" />
        <groups>
            <xsl:for-each select="$groups[generate-id()=generate-id(key('g',substring-before(text(), '.')))]">
                <xsl:variable name="name" select="substring-before(text(), '.')" />
                <group name="{$name}">
                    <xsl:for-each select="$groups[starts-with(text(), $name)][generate-id()=generate-id(key('g1',text()))]">
                        <elements name="{normalize-space(substring-after(text(), '.'))}">
                            <xsl:for-each select="/items/item[group/text()=current()/text()]/title">
                            <element>
                                <xsl:value-of select="text()" />
                            </element>
                            </xsl:for-each>
                        </elements>
                    </xsl:for-each>
                </group>
            </xsl:for-each>
        </groups>
    </xsl:template>
</xsl:stylesheet>


думал, решил добавить:
generate-id() - функция, которая генерирует уникальный идентификатор для данной ноды на пространстве документа.

generate-id(key('g',substring-before(text(), '.'))) - тоже генерирует уникальный идентификатор, на том же пространстве документа. Разница лишь в том, что она это делает на пространстве имен ключей. В ключи попадают только уникальные ноды, которые встретились первыми.

Одна и та же нода получит одинаковый идентификатор обоими функциями, если она попала в пространство ключей и соответственно разные идентификаторы, если она вне пространства ключей.

Это сообщение отредактировал(а) magelan - 15.7.2010, 17:38
PM MAIL   Вверх
Mephisto
Дата 15.7.2010, 22:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Волкъ
***


Профиль
Группа: Завсегдатай
Сообщений: 1818
Регистрация: 27.8.2003
Где: Питер

Репутация: нет
Всего: 34



magelan, уфф. Пока синтаксически мне не совсем понятно, особенно 
Код

/items/item[group/text()=current()/text()]/title

Пошел дальше дочитывать умные книжки. 
Спасибо!
PM   Вверх
magelan
Дата 16.7.2010, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


потерял xPath
**


Профиль
Группа: Участник
Сообщений: 393
Регистрация: 5.4.2010

Репутация: 7
Всего: 16



смущает current()?

эту строку:
Код

<xsl:for-each select="/items/item[group/text()=current()/text()]/title">

можно было записать так:
Код

<xsl:variable name="el_text" select="text()" />
<xsl:for-each select="/items/item[group/text()=$el_text]/title">



PM MAIL   Вверх
Mephisto
Дата 16.7.2010, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Волкъ
***


Профиль
Группа: Завсегдатай
Сообщений: 1818
Регистрация: 27.8.2003
Где: Питер

Репутация: нет
Всего: 34



У меня вообще проблемы с XPath пока  smile

Добавлено через 32 секунды
Код

/items/item[group/text()=$el_text]/title

Это тоже смущает. Не до конца понимаю. 
PM   Вверх
magelan
Дата 16.7.2010, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


потерял xPath
**


Профиль
Группа: Участник
Сообщений: 393
Регистрация: 5.4.2010

Репутация: 7
Всего: 16



Что именно?
давайте разбираться, это достаточно простое xPath выражение.

Иногда приходится писать весьма злые икспасы, от которых у коллег сносит крышу:
Код

$sprice/payservices/Object/Object/Object[@Type='M_SERVICE_PRICE'][Property[@Name='SHOW4TARIF']/text()='true'][Property[@Name='TARIFS']/Object[@Id = $id] or not( Property[@Name='TARIFS']/Object )]


PM MAIL   Вверх
Mephisto
Дата 16.7.2010, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Волкъ
***


Профиль
Группа: Завсегдатай
Сообщений: 1818
Регистрация: 27.8.2003
Где: Питер

Репутация: нет
Всего: 34



magelan, снесло крышу не только у коллег, но и у разметки винграда  smile 
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "XML/XSLT"
diadiavova

Прежде чем опубликовать вопрос, попробуйте воспользоваться поиском - возможно тема уже поднималась.

Также рекомендуем Вам зайти в раздел FAQ ,раздел дополняется и, возможно, там вы увидите готовое решение.

Для ответов на часто задаваемые вопросы существует FAQ раздела. Новости можно публиковать в разделе новостей. Для статей так же есть специальный раздел

Желаем удачи в Вашем деле!


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, diadiavova.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | XML, XSL | Следующая тема »


 




[ Время генерации скрипта: 0.0739 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.