XSLT 转换在我删除根节点之前不起作用

XSLT Transform doesn't work until I remove root node

提问人:hazymat 提问时间:1/13/2016 最后编辑:hazymat 更新时间:10/4/2021 访问量:3402

问:

我正在尝试使用 XSLT 从 Met Office Web 服务中的以下 XML 中提取标题,但是我的 XSLT 选择返回空白。

源:

<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>

我的 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>

我已将根更改为 /RegionalFcst 并尝试了其他类似的更改,例如在 FcstPeriods 之前添加前导斜杠,但在我从源 XML 中删除第一行和最后一行之前没有任何效果 - 然后它就可以完美运行。

这在测试中很好,但我当然想使用 Met Office 提供的 Web 服务,这就是他们呈现它的方式。

有什么想法吗?

XML XSLT

评论

1赞 Joel M. Lamsen 1/13/2016
这是具有默认命名空间的另一种情况。搜索此网站以获取示例
1赞 Michael Kay 1/13/2016
具体来说,搜索“XSLT default namespace”会把你带到其他506位提出相同问题的人。
0赞 U. Windl 6/6/2023
@MichaelKay 然而,问题是,只有在你知道这是一个命名空间问题后,你才能搜索命名空间问题。
0赞 Michael Kay 6/7/2023
@UWindl 当然可以。我无意提出任何批评。每个人都会掉进这个大象陷阱一次。

答:

16赞 michael.hor257k 1/13/2016 #1

问题:您的 XML 将其元素放在命名空间中。

解决方案:在样式表中声明相同的命名空间,为其分配一个前缀,并使用该前缀对源 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>

评论

0赞 Stefan Dolezel 6/1/2017
谢谢,这也有助于解决我的问题。应该强调的是,这仅适用于默认命名空间“xmlns=...”。如果源 xml 文件中有任何其他限定的命名空间,则必须将它们添加到“xsl:stylesheet”中,在 xpath 中使用(不带默认命名空间的临时前缀),并添加到“exclude-result-prefixes”(作为空格分隔列表)。
0赞 michael.hor257k 6/1/2017
@StefanDolezel 否,这适用于源 XML 使用的任何命名空间。
0赞 Stefan Dolezel 6/1/2017
是的,它的工作方式相同。我的意思是,只有对于默认命名空间,才必须创建一个前缀(在上面的示例中为“met”)。如果源文件已经有一个限定的命名空间,例如“xmlns:myns=...”,则可以在 xslt 中使用这个前缀(或者如果更方便,可以重新标记它)。
0赞 Amir 10/29/2020
除了这个解决方案,还有其他选择吗?我正在使用的系统不支持扩展
0赞 michael.hor257k 10/29/2020
@Amir 什么扩展?这是纯 XPath/XSLT。
1赞 30thh 10/4/2021 #2

除了“michael.hor257k”的答案之外,还有另一种解决方案,用于 XSLT 的 2.0 版。

XSLT 2.0 版

使用属性。对于上面的示例,它看起来像这样:xpath-default-namespace

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

然后,您无需在 XPath 引用的每个元素中重复命名空间前缀:

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

而不是

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