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

Поиск:

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


Волкъ
***


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

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



Фух, снова запарился с этой задачкой. Уже несколько часов воюю и не могу добить такую задачку
Исходный 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>
  <item>
    <title>second blah-blah-blahjnsjkndcjksndjc</title>
    <group>second. some second tratata / kill this</group>
  </item>
</items>

Использую следующее преобразование:
Код

<?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>

Результат получаю следующий:
Код

<?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>
            <element>second blah-blah-blah</element>
        </elements>
        <elements name="some second tratata / kill this">
            <element>second blah-blah-blahjnsjkndcjksndjc</element>
        </elements>
    </group>
</groups>

В исходном XML группировку испортил влезшая подстрока  " / kill this". Никак не могу прибить все символы после " /". Ломается группировка :(
Нужно получить следующее:
Код

<?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>
            <element>second blah-blah-blah</element>
            <element>second blah-blah-blahjnsjkndcjksndjc</element>
        </elements>
    </group>
</groups>

PM   Вверх
magelan
Дата 30.9.2010, 21:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


потерял xPath
**


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

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



Код
<xsl:key name="e" match="/items/item/group" use="normalize-space(substring-before(substring-after(text(), '.'), '/'))" />
Код
<xsl:for-each select="$elems[generate-id()=generate-id(key('e', normalize-space(substring-before(substring-after(text(), '.'), '/'))))]">


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


Волкъ
***


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

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



magelan, я пробовал нечто подобное, но нужно нечто сложнее, ибо результат получается такой:
Код

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

Сложность в том что не всегда косая черта встречается.
Элементы:
Код

<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>
  <item>
    <title>second blah-blah-blahjnsjkndcjksndjc</title>
    <group>second. some second tratata / kill this</group>
  </item>

Должны попасть в одну группу:
Код

<elements name="some second tratata">

PM   Вверх
magelan
Дата 4.10.2010, 01:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


потерял xPath
**


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

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



Эх, заказываете платье на королевну, а суете в него товарку...
Для товарки, методом дяди Вовы задачку решаем, трансформер конечно встанет раком, ему прийдется обработать число нод в 3й степени:
Код
<?xml version="1.0" encoding="Windows-1251"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
    
<xsl:template match="/">
    <groups>
    <xsl:for-each select="/items/item">
        <xsl:variable name="groupName" select="substring-before( group/text(), '.')" />
        <xsl:if test="not( preceding-sibling::item[ starts-with( group/text(), $groupName )])">
            <group name="{$groupName}">
                <xsl:for-each select="/items/item[ starts-with( group/text(), $groupName )]">
                    <xsl:variable name="elementsName">
                        <xsl:choose>
                            <xsl:when test="contains( group/text(), '/' )">
                                <xsl:value-of select="normalize-space( substring-before( group/text(), '/' ))" />
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="normalize-space( group/text())" />
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:variable>
                    <xsl:if test="not( preceding-sibling::item[ starts-with( group/text(), $elementsName )])">
                        <elements name="{normalize-space( substring-after( $elementsName, '.' ))}">
                            <xsl:for-each select="/items/item[ starts-with( group/text(), $elementsName )]">
                                <element>
                                    <xsl:value-of select="title/text()" />
                                </element>
                            </xsl:for-each>
                        </elements>
                    </xsl:if>
                </xsl:for-each>
            </group>
        </xsl:if>
    </xsl:for-each>
    </groups>
</xsl:template>
</xsl:stylesheet>

Ежели вы таки влетели на несколько мегобайтный хмл и кэш трансформера лопнул, надо этот метод малость усовершенствовать, т.е. действительно использовать двухпроходный алгоритм, в первой части которого создать сортированный нодесет, возможно частично переработанный.
Вторым проходом пустить по нему рекурсивную функцию, которая будет действовать наподобие SAX парсера строя по сути дела не хмл, а строку нужного вам вида.

Это сообщение отредактировал(а) magelan - 4.10.2010, 01:23
PM MAIL   Вверх
Mephisto
Дата 4.10.2010, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Волкъ
***


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

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



Цитата(magelan @  4.10.2010,  02:21 Найти цитируемый пост)
Эх, заказываете платье на королевну, а суете в него товарку...

Да я сам расстроился когда такое увидел :( Я просто с различных ресурсов собираю данные в XML формате и объединяю все в один с известным форматом, который позже обрабатываю. Вот на одном из ресурсов такая пакость есть :(
Цитата(magelan @  4.10.2010,  02:21 Найти цитируемый пост)
Ежели вы таки влетели на несколько мегобайтный хмл и кэш трансформера лопнул, надо этот метод малость усовершенствовать, т.е. действительно использовать двухпроходный алгоритм, в первой части которого создать сортированный нодесет, возможно частично переработанный.

В моем случае это вряд ли случится. Записей не так много.

Спасибо за помощь.  smile 
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "XML/XSLT"
diadiavova

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

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

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

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


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

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


 




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


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

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