Xslt: сложное преобразование из Xml в Xml

Тема в разделе "HTML, CSS, XML, JavaScript", создана пользователем Kottt, 17 мар 2010.

Наш партнер Genesis Hackspace
  1. Kottt

    Kottt Гость

    Встала такая тестовая задачка.

    1. Создать XSD схему с типами:

    · Комплексный тип – Работник. С элементами: имя, пол, зарплата, название департамента;

    · Комплексный тип – Отдел. Атрибуты: название отдела, средняя зарплата по отделу. Элемент: СписокРаботников;

    · Комплексный тип – СписокИменРаботников. Элемент – имя работника.

    2. Создать XML содержащий 5 работников. Причем 3 работника работают в одном и том же отделе, а остальные в других отделах.

    3. Написать XSLT трансформацию, которая трансформирует XML файл со списком Работников в файл со списком Отделов.

    Вот что я сделал:

    ****************************************

    Файл firm.xml:

    ...

    <!--shcode--><pre><code class='XML'><firm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="firmScheme.xsd">

    <employee>
    <name>Sirik Sergei Alexandrovich</name>
    <gender>male</gender>
    <salary>600$</salary>
    <depName>A02</depName>
    </employee>
    <employee>
    <name>Ivanov Ivan Ivanovich</name>
    <gender>male</gender>
    <salary>500$</salary>
    <depName>A02</depName>
    </employee>
    <employee>
    <name>Petrov Ivan Denisovich</name>
    <gender>male</gender>
    <salary>620$</salary>
    <depName>A02</depName>
    </employee>
    <employee>
    <name>Kostukevich Sergi Alexandrovich</name>
    <gender>male</gender>
    <salary>450$</salary>
    <depName>A07</depName>
    </employee>
    <employee>
    <name>Lakizo Inna Anatolievna</name>
    <gender>female</gender>
    <salary>400$</salary>
    <depName>OIC</depName>
    </employee>
    </firm>[/CODE]

    *************************************************

    Файл firmScheme.xsd:

    ...

    <!--shcode--><pre><code class='XML'><xsd:element name="firm" type="firmType"/>

    <xsd:element name="comment" type="xsd:string"/>

    <xsd:complexType name="workerType">
    <xsd:sequence>
    <xsd:element name="name" type="xsd:string">
    </xsd:element>
    <xsd:element name="gender" type="xsd:string"/>
    <xsd:element name="salary" type="xsd:string"/>
    <xsd:element name="depName" type="xsd:string"/>
    </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="departmentType">
    <xsd:sequence>
    <xsd:element name="wokersList" type="xsd:string"/>
    </xsd:sequence>
    <xsd:attribute name="depName" type="xsd:string"/>
    <xsd:attribute name="averageSalary" type="xsd:string"/>
    </xsd:complexType>

    <xsd:complexType name="nameListWorkersType">
    <xsd:sequence>
    <xsd:element name="workerName" type="xsd:string"/>
    </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="firmType">
    <xsd:sequence>
    <xsd:element name="employee" type="workerType" maxOccurs="unbounded" minOccurs="0"/>
    <xsd:element name="dep" type="departmentType" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element name="nameList" type="nameListWorkersType" minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
    </xsd:complexType>

    </xsd:schema>[/CODE]

    ********************************************************

    Ну а с XSLT трансформацией с данными условиями - засада. Я, конечно, мало знаком с XSLT, но пару дней плотно посвятил изучению. И максимум получается трансформация, отображающая список отделов, где встречаются все отделы (даже если атрибут @depName у них одинаковый), ну и соответственно в элементе workersList присутствует только 1 работник.

    Помогите, пожалуйста, решить задачку:)
     
  2. Kottt

    Kottt Гость

    Видимо задал сильно общий вопрос)))

    ну, а если вот так:

    Написал я вот такую трансформацию:

    <!--shcode--><pre><code class='XML'><xsl:template match="firm">
    <firm>
    <xsl:apply-templates/>
    </firm>
    </xsl:template>
    <xsl:template match="employee">
    <dep>
    <xsl:attribute name="depName">
    <xsl:value-of select="depName"/>
    </xsl:attribute>
    <xsl:attribute name="averageSalary">
    <xsl:value-of select="salary"/>
    </xsl:attribute>
    <xsl:apply-templates/>
    </dep>
    </xsl:template>
    <xsl:template match="name">
    <workersList>
    <xsl:apply-templates/>
    <xsl:apply-templates select="name"/>
    </workersList>
    </xsl:template>
    <xsl:template match="gender"/>
    <xsl:template match="depName"/>
    <xsl:template match="salary"/>[/CODE]

    И на выходе получается вот такой XML:

    <!--shcode--><pre><code class='XML'><firm>
    <dep depName="A02" averageSalary="600$">
    <workersList>Sirik Sergei Alexandrovich</workersList>



    </dep>
    <dep depName="A02" averageSalary="500$">
    <workersList>Ivanov Ivan Ivanovich</workersList>



    </dep>
    <dep depName="A02" averageSalary="620$">
    <workersList>Petrov Ivan Denisovich</workersList>



    </dep>
    <dep depName="A07" averageSalary="450$">
    <workersList>Kostukevich Sergi Alexandrovich</workersList>



    </dep>
    <dep depName="OIC" averageSalary="400$">
    <workersList>Lakizo Inna Anatolievna</workersList>



    </dep>
    </firm>[/CODE]

    И вот вопрос: Какое условие надо поставить чтобы выводило тег <dep/> с уникальным атрибутом @depName только 1 раз???

    P.S.: ещё один маленький вопросик: Как избавиться от пустых строк в полученном XML???
     
  3. Kottt

    Kottt Гость

    Народ, ау. Тут че никто с XSLT толком не работал???

    Помогите плз: Какое условие поставить вместо "?????" чтобы выводило только те теги <dep> у которых атрибут @depName уникален??? Текст преобразуемого XML и XSD см. выше.

    <!--shcode--><pre><code class='XML'> <xsl:template match="employee">
    <xsl:if test="?????">
    <dep>
    <xsl:attribute name="depName">
    <xsl:value-of select="depName"/>
    </xsl:attribute>
    <xsl:attribute name="averageSalary">
    <xsl:value-of select="salary"/>
    </xsl:attribute>
    <xsl:apply-templates/>
    </dep>
    </xsl:if>
    </xsl:template>[/CODE]
     
  4. Kmet

    Kmet Well-Known Member
    Java Team

    Регистрация:
    25 май 2006
    Сообщения:
    1.032
    Симпатии:
    6
  5. Kottt

    Kottt Гость

    Спасибо большое за ссылочки. Теперь получается вот так вот:

    Трансформация:

    <!--shcode--><pre><code class='XML'> <xsl:template match="/">
    <firm>
    <xsl:apply-templates/>
    </firm>
    </xsl:template>
    <xsl:template match="firm">
    <xsl:variable name="unique-list"
    select="//depName[not(.=following::depName)]" />
    <xsl:for-each select="$unique-list">
    <dep>
    <xsl:attribute name="depName">
    <xsl:value-of select="."/>
    </xsl:attribute>
    <xsl:attribute name="averageSalary">
    <xsl:value-of select="preceding-sibling::salary"/>
    </xsl:attribute>
    <workersList>
    <xsl:apply-templates select="preceding-sibling::name" mode="workersList"/>
    </workersList>
    </dep>
    </xsl:for-each>
    </xsl:template>[/CODE]


    На выходе:

    <!--shcode--><pre><code class='XML'><firm>
    <dep depName="A07" averageSalary="450$">
    <workersList>Kostukevich Sergi Alexandrovich</workersList>
    </dep>
    <dep depName="OIC" averageSalary="400$">
    <workersList>Lakizo Inna Anatolievna</workersList>
    </dep>
    <dep depName="A02" averageSalary="500$">
    <workersList>Ivanov Ivan Ivanovich</workersList>
    </dep>
    </firm>[/CODE]

    Добавлено: Теперь парюсь как сделать так чтобы в элементе <workersList/> были все имена работников, работающих в данном отделе и в аттрибуте @averageSalary была соответственно средняя зарплата по отделу. Пока безуспешно:) Буду очень благодарен за помощь.
     
  6. Kottt

    Kottt Гость

    Ну вот короче такая трансформация у меня получилась:

    <!--shcode--><pre><code class='XML'><xsl:template match="/">
    <firm>
    <xsl:variable name="unique-list"
    select="//depName[not(.=following::depName)]" />
    <xsl:for-each select="$unique-list">
    <dep>
    <xsl:attribute name="depName">
    <xsl:value-of select="."/>
    </xsl:attribute>
    <xsl:attribute name="averageSalary">
    <xsl:choose>
    <xsl:when test=".=//depName[.=following::depName]">
    <xsl:apply-templates select="preceding-sibling::salary" mode="averageSalary"/>
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="preceding-sibling::salary"/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:attribute>
    <workersList>
    <xsl:value-of select="preceding-sibling::name"/>
    <xsl:if test=".=//depName[.=following::depName]">
    <xsl:apply-templates select="preceding-sibling::name" mode="workersList"/>
    </xsl:if>
    </workersList>
    </dep>
    </xsl:for-each>
    </firm>
    </xsl:template>

    <xsl:template match="name" mode="workersList">
    <xsl:variable name="notunique-list"
    select="//depName[.=following::depName]" />
    <xsl:for-each select="$notunique-list">
    <xsl:text> </xsl:text>
    <xsl:value-of select="preceding-sibling::name"/>
    </xsl:for-each>
    </xsl:template>

    <xsl:template match="salary" mode="averageSalary">
    <xsl:variable name="aSalary"
    select="//depName[.=following::depName]/preceding-sibling::salary | //depName[.=preceding::depName]/preceding-sibling::salary" /> <xsl:value-of select="(sum($aSalary) div count($aSalary)) + ((sum($aSalary) mod count($aSalary))*1000 div count($aSalary)) div 1000"/>
    </xsl:template>[/CODE]

    И на выходе вот:

    <!--shcode--><pre><code class='XML'><firm>
    <dep depName="A07" averageSalary="450">
    <workersList>Kostukevich Sergi Alexandrovich</workersList>
    </dep>
    <dep depName="OIC" averageSalary="400">
    <workersList>Lakizo Inna Anatolievna</workersList>
    </dep>
    <dep depName="A02" averageSalary="556">
    <workersList>Ivanov Ivan Ivanovich Sirik Sergei Alexandrovich Petrov Ivan Denisovich Fedorov Ivan Ivanovich</workersList>
    </dep>
    </firm>[/CODE]

    Конечно кривовато сделано, но уж как получилось. Пожалуйста советуйте как улучшить. И есче вопросик: С расчетом средней зарплаты специально поубирал знаки обозначения валюты($) в исходном XML. Пробовал со знаками там используя substring-before() - не получилось. Если посоветуете как - буду очень признателен:)
     
Загрузка...
Похожие Темы - Xslt сложное преобразование
  1. otokys
    Ответов:
    0
    Просмотров:
    187
  2. Megaworld
    Ответов:
    0
    Просмотров:
    1.151
  3. Eugen
    Ответов:
    0
    Просмотров:
    1.328
  4. Eugen
    Ответов:
    70
    Просмотров:
    13.991
  5. VladSh
    Ответов:
    12
    Просмотров:
    6.655

Поделиться этой страницей