Назначение столбцов на основе порядка элементов в XML - PullRequest
2 голосов
/ 22 сентября 2011

Мой XML показан ниже:

<?xml version="1.0" encoding="UTF-8"?>
<JobListing>
    <ColumnOrder>
        <columnId>4</columnId>
        <columnId>2</columnId>
        <columnId>5</columnId>
        <columnId>1</columnId>
        <columnId>3</columnId>
    </ColumnOrder>
    <Jobs>
        <Job>
            <title>Java Developer</title>
            <code>JAVA</code>
            <openings>10</openings>
            <location>USA</location>
            <duration>6 months</duration>
        </Job>
        <Job>
            <title>.NET Developer</title>
            <code>DOTNET</code>
            <openings>10</openings>
            <location>USA</location>
            <duration>6 months</duration>
        </Job>
    </Jobs>
</JobListing>

У меня есть конкретное требование, чтобы задания были перечислены на странице HTML на основе ColumnOrder, указанной в XML. Внутри каждый columnId отображается в столбец, как указано ниже:

  • 1 -> Заголовок
  • 2 -> Код
  • 3 -> отверстия
  • 4 -> Местоположение
  • 5 -> Продолжительность

В этом случае, например, на странице списка вакансий должны быть перечислены столбцы в следующем порядке - Location, Code, Duration, Title, Openings. Я ожидаю что-то вроде как объяснено ниже:

<tr>
  loop jobs
     for each columnorder
              if(columnId == 1)
                        <td>get Title</td>
              else if (columnId == 2)
                        <td>get Code</td>
              else if (columnId == 3)
                        <td>get Openings</td>
              else if (columnId == 4)
                        <td>get Location</td>
              else if (columnId == 5)
                        <td>get Duration</td>
              end if
     end columnorder
  end jobs
</tr>   

Как мне добиться этого с помощью XSLT?

Любая помощь или различные идеи / предложения будут с благодарностью.

РЕДАКТИРОВАТЬ: Элементы <Job> в XML (заголовок, открытия, местоположение, продолжительность, код) не обязательно в том же порядке. На самом деле, в нашей текущей среде он генерируется в порядке возрастания (например, код, продолжительность, местоположение, открытия, заголовок). Как заставить это работать без учета порядка элементов <Job>?

Ответы [ 3 ]

2 голосов
/ 22 сентября 2011

Это преобразование работает, даже когда дочерние элементы Job смешаны в любом порядке :

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my" exclude-result-prefixes="my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>

     <my:Mapping>
       <id val="1">title</id>
       <id val="2">code</id>
       <id val="3">openings</id>
       <id val="4">location</id>
       <id val="5">duration</id>
     </my:Mapping>

     <xsl:variable name="vOrder" select="/*/ColumnOrder/*"/>

     <xsl:variable name="vMap" select=
          "document('')/*/my:Mapping/*"/>

     <xsl:template match="Jobs">
         <table>
          <xsl:apply-templates/>
         </table>
     </xsl:template>

     <xsl:template match="Job">
      <tr>
       <xsl:apply-templates select="*">
         <xsl:sort data-type="number" select=
          "count($vOrder
                      [. = $vMap
                              [. = name(current())]/@val
                      ]
                       /preceding-sibling::*
                 )
          "/>
       </xsl:apply-templates>
      </tr>
     </xsl:template>

     <xsl:template match="Job/*">
      <td><xsl:value-of select="."/></td>
     </xsl:template>

     <xsl:template match="ColumnOrder"/>
</xsl:stylesheet>

При применении к предоставленному документу XML :

<JobListing>
    <ColumnOrder>
        <columnId>4</columnId>
        <columnId>2</columnId>
        <columnId>5</columnId>
        <columnId>1</columnId>
        <columnId>3</columnId>
    </ColumnOrder>
    <Jobs>
        <Job>
            <title>Java Developer</title>
            <code>JAVA</code>
            <openings>10</openings>
            <location>USA</location>
            <duration>6 months</duration>
        </Job>
        <Job>
            <title>.NET Developer</title>
            <code>DOTNET</code>
            <openings>10</openings>
            <location>USA</location>
            <duration>6 months</duration>
        </Job>
    </Jobs>
</JobListing>

Требуется правильный результат :

<table>
   <tr>
      <td>USA</td>
      <td>JAVA</td>
      <td>6 months</td>
      <td>Java Developer</td>
      <td>10</td>
   </tr>
   <tr>
      <td>USA</td>
      <td>DOTNET</td>
      <td>6 months</td>
      <td>.NET Developer</td>
      <td>10</td>
   </tr>
</table>
1 голос
/ 22 сентября 2011

Эта таблица стилей:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="JobListing">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="Jobs">
        <table>
            <xsl:apply-templates />
        </table>
    </xsl:template>

    <xsl:template match="Job">
        <tr>
            <xsl:variable name="currentJob" select="."/>
            <xsl:for-each select="/JobListing/ColumnOrder/columnId">
                <xsl:choose>
                    <xsl:when test="current()=1">
                        <xsl:apply-templates select="$currentJob/title" />
                    </xsl:when>
                    <xsl:when test="current()=2">
                        <xsl:apply-templates select="$currentJob/code" />
                    </xsl:when>
                    <xsl:when test="current()=3">
                        <xsl:apply-templates select="$currentJob/openings" />
                    </xsl:when>
                    <xsl:when test="current()=4">
                        <xsl:apply-templates select="$currentJob/location" />
                    </xsl:when>
                    <xsl:when test="current()=5">
                        <xsl:apply-templates select="$currentJob/duration" />
                    </xsl:when>
                </xsl:choose>

            </xsl:for-each>
        </tr>
    </xsl:template>

    <xsl:template match="Job/*">
        <td>
            <xsl:apply-templates />
        </td>
    </xsl:template>

    <!--Don't render ColumnOrder-->
    <xsl:template match="ColumnOrder"/>
</xsl:stylesheet>

При применении к вводу сэмпла получается следующий вывод:

<?xml version="1.0" encoding="UTF-8"?>
<table>
    <tr>
        <td>USA</td>
        <td>JAVA</td>
        <td>6 months</td>
        <td>Java Developer</td>
        <td>10</td>
    </tr>
    <tr>
        <td>USA</td>
        <td>DOTNET</td>
        <td>6 months</td>
        <td>.NET Developer</td>
        <td>10</td>
    </tr>
</table>
0 голосов
/ 22 сентября 2011
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

    <xsl:template match="Job">
        <xsl:copy>
            <xsl:apply-templates select="../../ColumnOrder/columnId">
                <xsl:with-param name="pos" select="position()"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="columnId">
        <xsl:param name="pos"/>

        <xsl:copy-of select="../../Jobs/Job[position() = $pos]/*[position() = current()/.]"/>

    </xsl:template>

</xsl:stylesheet>

Выход:

<Job>
  <location>USA</location>
  <code>JAVA</code>
  <duration>6 months</duration>
  <title>Java Developer</title>
  <openings>10</openings>
</Job>
<Job>
  <location>USA</location>
  <code>DOTNET</code>
  <duration>6 months</duration>
  <title>.NET Developer</title>
  <openings>10</openings>
</Job>
...