2
votes

I'm trying to import XML data via XSLT into Adobe InDesign. InDesign doesnt seem to be able to use attributes, even though it can see the attributes.

I have access to free weather data in this format : http://www.yr.no/sted/Norge/Oslo/Oslo/Oslo/varsel.xml

I'm not sure if the way I do the XSLT to transform attributes to regular XML format is the best, but it works.

The problem I'm having is that I need the weather data for tomorrow, but I only get the data for today. The data is stored in the weatherdata/forecast/tabular/time.

I use <xsl:param name="speedmps" select="weatherdata/forecast/tabular/time[@period='2']/windSpeed/@mps" /> to select the data, but this only chooses the first match. And the first match is todays weather (from 12:00 to 18:00), what I want is the second match (the second period='2' match, that is tomorrow 12:00 to 18:00). The day is presented in 4 periods, and the XML file got the forecast for several days. Ideally I would want to make one XSLT for todays weather, one for tomorrows weather and so on.

My code is mostly cut and paste, and then I try to edit it to do what I want it to. I tried making a if block, but I failed to find any examples I could build onto. My skills in XSLT are too basic at the moment, and I have a short deadline. And what I discovered in the source data is that the periods change according to when in the day you fetch the data. So I couldnt say that it should select the 6th block, since tomorrows period='2' may be the 5th at this time of the day. (period='0' is 00:00 to 09:00 so period 0 gets deleted after 09:00 and so on).

The first match right now is:

<time from="2013-02-27T12:00:00" to="2013-02-27T18:00:00" period="2">
    <!-- Valid from 2013-02-27T12:00:00 to 2013-02-27T18:00:00 -->
    <symbol number="1" name="Klarvær" var="01d" />
    <precipitation value="0" />
    <!-- Valid at 2013-02-27T12:00:00 -->
    <windDirection deg="187.2" code="S" name="Sør" />
    <windSpeed mps="1.5" name="Flau vind" />
    <temperature unit="celsius" value="-1" />
    <pressure unit="hPa" value="1030.2" />
  </time>    

The second match right now is:

<time from="2013-02-28T12:00:00" to="2013-02-28T18:00:00" period="2">
    <!-- Valid from 2013-02-28T12:00:00 to 2013-02-28T18:00:00 -->
    <symbol number="1" name="Klarvær" var="01d" />
    <precipitation value="0" />
    <!-- Valid at 2013-02-28T12:00:00 -->
    <windDirection deg="181.3" code="S" name="Sør" />
    <windSpeed mps="3.1" name="Svak vind" />
    <temperature unit="celsius" value="2" />
    <pressure unit="hPa" value="1015.7" />
  </time>

I'm sorry but english is not my first language, I tried to explain as good as I can.

This is my XSLT code:

    <?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="ISO-8859-1" indent="yes" omit-xml-declaration="no" cdata-section-elements="" />

<!-- params -->
<xsl:param name="location" select="weatherdata/location/name"/>
<xsl:param name="alternate" select="weatherdata/links/link[@id='overview']/@url"/>
<xsl:param name="base" select="'file:///d:/temp/yr/sky/'"/>
<!-- We use the text forecast dates or? -->
<xsl:param name="lastupdate" select="weatherdata/meta/lastupdate" />
<xsl:param name="symbolnumber" select="weatherdata/forecast/tabular/time[@period='2']/symbol/@number" />
<xsl:param name="symbolname" select="weatherdata/forecast/tabular/time[@period='2']/symbol/@name" />
<xsl:param name="symbolvar" select="weatherdata/forecast/tabular/time[@period='2']/symbol/@var" />
<xsl:param name="precip" select="weatherdata/forecast/tabular/time[@period='2']/precipitation/@value" />
<xsl:param name="directiondeg" select="weatherdata/forecast/tabular/time[@period='2']/windDirection/@deg" />
<xsl:param name="directioncode" select="weatherdata/forecast/tabular/time[@period='2']/windDirection/@code" />
<xsl:param name="directionname" select="weatherdata/forecast/tabular/time[@period='2']/windDirection/@name" />
<xsl:param name="speedmps" select="weatherdata/forecast/tabular/time[@period='2']/windSpeed/@mps" />
<xsl:param name="speedname" select="weatherdata/forecast/tabular/time[@period='2']/windSpeed/@name" />
<xsl:param name="tempvalue" select="weatherdata/forecast/tabular/time[@period='2']/temperature/@value" />

<xsl:template match="/">
<yr>
<testtag>   
    <title><xsl:value-of select="$location"/></title>
    <alternate><xsl:value-of select="$alternate"/></alternate>
    <base><xsl:value-of select="$base"/></base>
    <lastupdate><xsl:value-of select="$lastupdate"/></lastupdate>
    <symbolvar><xsl:value-of select="$symbolvar"/></symbolvar>
    <symbolnr><xsl:value-of select="$symbolnumber"/></symbolnr>
    <symbolname><xsl:value-of select="$symbolname"/></symbolname>
    <precip><xsl:value-of select="$precip"/></precip>
    <tempval><xsl:value-of select="$tempvalue"/></tempval>
    <speedname><xsl:value-of select="$speedname"/></speedname>
    <speedmps><xsl:value-of select="$speedmps"/></speedmps>
    <dirdeg><xsl:value-of select="$directiondeg"/></dirdeg>
    <dircode><xsl:value-of select="$directioncode"/></dircode>
    <dirname><xsl:value-of select="$directionname"/></dirname>
    <Image><xsl:attribute name="href"><xsl:value-of select="$base"/><xsl:value-of select="$symbolvar"/>.png</xsl:attribute></Image>
</testtag>  
</yr>
</xsl:template> 

</xsl:stylesheet>
1

1 Answers

0
votes

If you want the second time[@period = '2'] element (in other words, if I understood you correctly), you can use time[@period='2'][2].

However, your stylesheet is not really how you do XSLT. Instead of storing node values in <xsl:param> elements and then processing them later, the convention is — and I'm simplifying quite a bit here, obviously — to have an <xsl:template> element for each node in the input document you want to process.

There are many ways to achieve what you want, but you can use the stylesheet below as a starting point for your code.

Input

The second <time> with a @period attribute value of 2:

<time from="2013-02-28T12:00:00" to="2013-02-28T18:00:00" period="2">
    <!-- Valid from 2013-02-28T12:00:00 to 2013-02-28T18:00:00 -->
    <symbol number="1" name="Klarvær" var="01d" />
    <precipitation value="0" />
    <!-- Valid at 2013-02-28T12:00:00 -->
    <windDirection deg="181.3" code="S" name="Sør" />
    <windSpeed mps="3.1" name="Svak vind" />
    <temperature unit="celsius" value="2" />
    <pressure unit="hPa" value="1015.7" />
</time>

Stylesheet

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" encoding="ISO-8859-1" indent="yes" omit-xml-declaration="no" cdata-section-elements=""/>
  <xsl:strip-space elements="*"/>

  <!--
  The position of the time[@period = '2'] element; indexing starts from 1.
  You can pass in this parameter to the transformation if you want the
  time[@period = '2'] element in some other position.
  -->
  <xsl:param name="time" select="2"/>
  <xsl:param name="base" select="'file:///d:/temp/yr/sky/'"/>

  <xsl:template match="/">
    <yr>
      <testtag>
        <xsl:apply-templates select="weatherdata"/>
      </testtag>
    </yr>
  </xsl:template>

  <xsl:template match="weatherdata">
    <xsl:apply-templates select="location/name"/>
    <xsl:apply-templates select="links/link[@id = 'overview']"/>
    <base><xsl:value-of select="$base"/></base>
    <xsl:apply-templates select="meta/lastupdate"/>
    <!-- Apply the <time period="2"> element in $time position -->
    <xsl:apply-templates select="forecast/tabular/time[@period = '2'][number($time)]"/>
  </xsl:template>

  <xsl:template match="tabular/time">
    <xsl:apply-templates select="symbol"/>
    <xsl:apply-templates select="precipitation"/>
    <xsl:apply-templates select="temperature"/>
    <xsl:apply-templates select="windSpeed"/>
    <xsl:apply-templates select="windDirection"/>

    <!--
    Use attribute value template (AVT) to construct the attribute value:
    http://lenzconsulting.com/how-xslt-works/#attribute_value_templates
    -->
    <Image href="{concat($base, symbol/@var, '.png')}"/>
  </xsl:template>

  <xsl:template match="location/name">
    <title>
      <xsl:value-of select="."/>
    </title>
  </xsl:template>

  <xsl:template match="links/link">
    <alternate>
      <!-- Use the value of the @url attribute of this element -->
      <xsl:value-of select="@url"/>
    </alternate>
  </xsl:template>

  <xsl:template match="temperature">
    <tempval>
      <xsl:value-of select="@value"/>
    </tempval>
  </xsl:template>

  <xsl:template match="windSpeed">
    <speedname>
      <xsl:value-of select="@name"/>
    </speedname>

    <speedmps>
      <xsl:value-of select="@mps"/>
    </speedmps>
  </xsl:template>

  <xsl:template match="windDirection">
    <dirdeg>
      <xsl:value-of select="@deg"/>
    </dirdeg>

    <dircode>
      <xsl:value-of select="@code"/>
    </dircode>

    <dirname>
      <xsl:value-of select="@name"/>
    </dirname>
  </xsl:template>

  <xsl:template match="precipitation">
    <precip>
      <xsl:value-of select="@value"/>
    </precip>
  </xsl:template>

  <xsl:template match="symbol">
    <symbolvar>
      <xsl:value-of select="@var"/>
    </symbolvar>

    <symbolnr>
      <xsl:value-of select="@number"/>
    </symbolnr>

    <symbolname>
      <xsl:value-of select="@name"/>
    </symbolname>
  </xsl:template>

  <xsl:template match="lastupdate">
    <!-- Copy the original node as is -->
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Output

<?xml version="1.0" encoding="ISO-8859-1"?>
<yr>
  <testtag>
    <title>Oslo</title>
    <alternate>http://www.yr.no/sted/Norge/Oslo/Oslo/Oslo/</alternate>
    <base>file:///d:/temp/yr/sky/</base>
    <lastupdate>2013-02-27T06:39:00</lastupdate>
    <symbolvar>01d</symbolvar>
    <symbolnr>1</symbolnr>
    <symbolname>Klarv?r</symbolname>
    <precip>0</precip>
    <tempval>2</tempval>
    <speedname>Svak vind</speedname>
    <speedmps>3.1</speedmps>
    <dirdeg>181.3</dirdeg>
    <dircode>S</dircode>
    <dirname>S?r</dirname>
    <Image href="file:///d:/temp/yr/sky/01d.png"/>
  </testtag>
</yr>