XSLT Transform doesn't work until I remove root node
Asked Answered
L

2

5

I'm trying to extract the headline from the below XML from the Met Office web service using XSLT, however my XSLT select returns blank.

SOURCE:

<RegionalFcst xmlns="www.metoffice.gov.uk/xml/metoRegionalFcst" createdOn="2016-01-13T02:14:39" issuedAt="2016-01-13T04:00:00" regionId="se">
 <FcstPeriods>
  <Period id="day1to2">
   <Paragraph title="Headline:">Frosty start. Bright or sunny day.</Paragraph>
   <Paragraph title="Today:">A clear and frosty start in west, but cloudier in Kent with isolated showers. Then dry with sunny periods. Increasing cloud in west later will bring coastal showers with freshening southerly winds. Chilly inland, but less cold near coasts. Maximum Temperature 8C.</Paragraph>
  </Period>
 </FcstPeriods>
</RegionalFcst>

My XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
   <xsl:value-of select="FcstPeriods/Period/Paragraph"/>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

I've changed the root to /RegionalFcst and attempted other similar changes, such as adding a leading slash before FcstPeriods, but nothing works until I remove the first and last line from the source XML - then it works perfectly.

This is fine in testing, but of course I want to use the web service provided by Met Office and that's how they present it.

Any ideas?

Legault answered 13/1, 2016 at 4:36 Comment(4)
it is another case of having a default namespace. search this site for examplesLaellaertes
Specifically, searching for "XSLT default namespace" will take you to 506 other people who have asked the same question.Discrepancy
@MichaelKay The thing however is that you can only search for namespace issues once you know that it's a namespace issue.Ulrica
@UWindl Absolutely. I didn't intend any criticism. Everyone falls into this elephant trap once.Discrepancy
D
16

The problem: your XML puts its elements in a namespace.

Solution: declare the same namespace in your stylesheet, assign it a prefix and use that prefix to address the elements in the source XML:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:met="www.metoffice.gov.uk/xml/metoRegionalFcst"
exclude-result-prefixes="met">
<xsl:template match="/">
  <html>
  <body>
   <xsl:value-of select="met:RegionalFcst/met:FcstPeriods/met:Period/met:Paragraph[@title='Headline:']"/>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>
Dryly answered 13/1, 2016 at 9:17 Comment(8)
Thanks this helped solving my problem, too. It should be emphasized that this only works for the default namespace "xmlns=...". If there are any other qualified namespaces in the source xml file they have to be added to "xsl:stylesheet", used in the xpath (without the temporary prefix for the default namespace), and added to "exclude-result-prefixes" (as space separated list).Balbur
@StefanDolezel No, this works for any namespaces used by the source XML.Dryly
Yes, it works the same way. I meant that only for the default namespace a prefix has to be created ("met" in the example above). If the source file already has a qualified namespace, e.g. "xmlns:myns=...", one may just use this prefix in the xslt (or relabel it if it is more convenient).Balbur
Is there any alternative to this solution. The system I am working with doesn't support the extensionsTodtoday
@Todtoday What extensions? This is pure XPath/XSLT.Dryly
Sorry I was wrong, the error was comming from the setting in the version setting. By mistake i was using version 1 and since this is code is written for version 2 i was getting error. My bad! Your solution works perfectly.Todtoday
@Todtoday Do note that the above is an XSLT 1.0 solution. If you're using XSLT 2.0 or higher, you can take advantage of xpath-default-namespace.Dryly
well funny because it didnt work till I changed the version to 2. Thanks, tomorrow I will try this solution.Todtoday
S
1

Additional to the answer of "michael.hor257k", there is another solution, for the version 2.0 of XSLT.

XSLT 2.0

Use xpath-default-namespace attribute. For the example above it looks like this:

<xsl:stylesheet xpath-default-namespace="www.metoffice.gov.uk/xml/metoRegionalFcst" ... >

Then you don't need to repeat the namespace prefix in every element referenced by XPath:

<xsl:value-of select="FcstPeriods/Period/Paragraph"/>

instead of

<xsl:value-of select="met:FcstPeriods/met:Period/met:Paragraph"/>
Shanta answered 4/10, 2021 at 7:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.