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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Интересная задачка по XSL, хитро отформатировать xml-ку 
:(
    Опции темы
tomboy1
Дата 29.2.2012, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Добрый день, форумчане!
Только зарегистрировался, встречайте новичка!  smile 

Собственно, интересный, на мой взгляд, сабж.
Есть xml-файл с примерно следующей разметкой:

Код

<?xml version="1.0" encoding="UTF-8"?>
<intermediate name="Simple" package="simple">
   <type wireName="point"  name="Point"
         package="simple.data"
         isAbstract="no"
         base="Element">
      <field name="lat" type="double" isOptional="yes" isArray="no" wireName="lat"
              isSimple="yes"/>
      <field name="lon" type="double" isOptional="yes" isArray="no" wireName="lon"
              isSimple="yes"/>
      <field name="lur" type="double" isOptional="yes" isArray="no" wireName="lur"
              isSimple="yes"/>
      <field name="lit" type="double" isOptional="no" isArray="no" wireName="lit"
              isSimple="yes"/>
   </type>
</intermediate>

Необходимо из него вывести текстовый файл с примерно таким содержанием:
Код

 - point: [lat, lon, lur, lit]
, НО!!!
Не совсем так. Строчек point должно быть столько, сколько есть всевозможных комбинаций опциональных параметров (isOptional="yes") + обязательных (isOptional="no"). То есть точно вывод должен быть такой:
Код

 - point: [lat, lon, lur, lit]
 - point: [lon, lur, lit]
 - point: [lat, lur, lit]
 - point: [lat, lon, lit]
 - point: [lat, lit]
 - point: [lon, lit]
 - point: [lur, lit]
 - point: [lit]

или в другом порядке, это неважно. Строки потом можно отформатировать.
Последнее, что пришло в голову - это следующее:
Код

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:navbuilder="http://www.navbuilder.com">
    <xsl:output method="text" omit-xml-declaration="yes" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:template match="/">
        <xsl:apply-templates />
        <xsl:call-template name="recursive" />
    </xsl:template>

    <xsl:template name = "recursive" match="package">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="type">
        <xsl:text> - </xsl:text>
        <xsl:value-of select="@wireName" />
        <xsl:text>: [</xsl:text>
        <xsl:for-each select="field">
            <xsl:sort select="@wireName" data-type="text" order="ascending"/>
            <xsl:if test="@isSimple = 'yes'">
            <xsl:choose>
                <xsl:when test="@isOptional = 'yes'">
                    <xsl:value-of select="@wireName" />
                    <xsl:text>]</xsl:text>
                    <xsl:text>&#xa;</xsl:text>
                    <xsl:call-template name="recursive" />
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="@wireName" />
                    <xsl:if test="position() != last()">
                        <xsl:text>, </xsl:text>
                    </xsl:if>
                </xsl:otherwise>
            </xsl:choose>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>]</xsl:text>
        <xsl:text>&#xa;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

Но это все равно должным образом не работает. Кто-нибудь может помочь? Вообще, обход всевозможных вариантов средством xsl возможен? Бьюсь с этим уже неделю. Боюсь, что скоро мысли иссякнут  smile 

Это сообщение отредактировал(а) tomboy1 - 29.2.2012, 22:21
PM MAIL   Вверх
diadiavova
Дата 29.2.2012, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



tomboy1, честно говоря, из объяснения я не понял по какому принципу формируются выходные данные.


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


Новичок



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

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



Цитата(diadiavova @ 29.2.2012,  19:32)
tomboy1, честно говоря, из объяснения я не понял по какому принципу формируются выходные данные.

Спасибо за внимание.
У поля field в xml-файле есть атрибут isOptional. Если этот атрибут равен yes, то поле опционально, т.е. может учитываться для выходных данных, а может и нет. А если этот атрибут равен no, то это поле является обязательным.
Выходные данные формируются так: строчка выходных данных - это заголовок (name из type) + комбинация обязательных и не обязательных полей. Кол-во таких строчек = кол-ву комбинаций. Итого для той xml получаем:
Код

 - point: [lat, lon, lur, lit]
 - point: [lon, lur, lit]
 - point: [lat, lur, lit]
 - point: [lat, lon, lit]
 - point: [lat, lit]
 - point: [lon, lit]
 - point: [lur, lit]
 - point: [lit]
,
где point - значение атрибута name в тэге type (ставится перед каждой комбинацией полей field),
lat, lon, lur, lit - т.е. то, что в квадратных скобках - всевозможные комбинации атрибутов name в field в зависимости от опциональности.

Т.е., например, для следующей xml:
Код

<?xml version="1.0" encoding="UTF-8"?>
<intermediate name="Simple" package="simple">
   <type name="point" package="simple.data">
      
      <field name="lur" isOptional="yes" />
      <field name="lit" isOptional="no" />
   </type>
</intermediate>

выходные данные будут такими:
Код

 - point: [lur, lit]
 - point: [lit]


А для такой xml (добавил еще одно field с isOptional="yes"):
Код

<?xml version="1.0" encoding="UTF-8"?>
<intermediate name="Simple" package="simple">
   <type name="point" package="simple.data">

      <field name="lon" isOptional="yes" />
      <field name="lur" isOptional="yes" />
      <field name="lit" isOptional="no" />
   </type>
</intermediate>

выходные данные должны быть такими:
Код

 - point: [lur, lon, lit]
 - point: [lon, lit]
 - point: [lur, lit]
 - point: [lit]


Я сделал xml-ки максимально простыми, чтобы было понятно, как необходимо построить выходные данные. Сейчас должно быть понятно.
П.С. Порядок атрибутов в квадратных скобках не учитывается. Т.е. для последней xml все равно, что " - point: [lur, lon, lit]", что " - point: [lon, lur, lit]". Не учитывается, потому что эти атрибуты потом все равно будут сортироваться.
PM MAIL   Вверх
diadiavova
Дата 29.2.2012, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



tomboy1, то есть ты хочешь, чтобы преобразование выдавало все комбинации возможных параметров?
Идея есть. Достаточно геморно, но, как мне кажется, вполне решаемо. Значит во всех случаях сначала выставляем обязательные параметры (чтобы больше о них не думать). 

Что касается необязательных, то тут сначала подсчитываем сколько будет комбинаций. Это достаточно легко сделать, поскольку количество их будет равно 2^n, где n - количество необязательных параметров. 

В языке, поддерживающем императивную вычислительную логику, на этом этапе следовало бы написать цикл, где счетчик изменялся бы от 1 до вычисленного числа (2^n). Но поскольку тут циклов нет, его придется заменить рекурсивным шаблоном, в котором роль счетчика будет выполнять параметр и отсчет лучше вести в обратном направлении. 

Внутри шаблона, для того, чтобы определить нужно в данной итерации вставлять тот или иной параметр, можно воспользоваться двоичной системой счисления, то есть представить текущее значение счетчика в двоичной системе и в таком представлении каждый разряд двоичного числа будет соответствовать одному параметру(если это единица - вставляем параметр, если ноль - нет).

Реализация этого всего достаточно громоздка, но если ты идею понял, то видимо ничего сверхъестественного нет.


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


Новичок



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

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



Примерно понял. Будем думать, спасибо.
Да уж, задачка не из тривиальных  smile 
PM MAIL   Вверх
magelan
Дата 2.3.2012, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


потерял xPath
**


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

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



Как-то так:


Код

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

    <xsl:output method="html" encoding="windows-1251" />

    <xsl:template match="/">
        <xsl:call-template name="f">
            <xsl:with-param name="fld" select="/intermediate/type/field[1]" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="f">
        <xsl:param name="fld" />
        <xsl:param name="prefix" select="'- point: ['" />
        <xsl:choose>
            <xsl:when test="$fld/following-sibling::field">
                <xsl:call-template name="f">
                    <xsl:with-param name="fld" select="$fld/following-sibling::field" />
                    <xsl:with-param name="prefix" select="concat( $prefix, $fld/@name, ',' )" />
                </xsl:call-template>
    
                <xsl:if test="$fld/@isOptional='yes' and $fld/following-sibling::field">
                    <xsl:call-template name="f">
                        <xsl:with-param name="fld" select="$fld/following-sibling::field" />
                        <xsl:with-param name="prefix" select="$prefix" />
                    </xsl:call-template>
                </xsl:if>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="concat( $prefix, $fld/@name, ']' )" />
                <br />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>


Это сообщение отредактировал(а) magelan - 2.3.2012, 15:09
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "XML/XSLT"
diadiavova

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

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

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

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


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

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


 




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


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

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