无法将模板应用于子元素

Can't apply template to child element

我有一个 XML 文件,其中包含嵌套在 <p> 元素内的另一个元素中的子元素。我的 XSLT 很好地提取了 <p> 元素,但它忽略了 <span>。我知道它与 xPath 有关,但我不知道如何使用此 XSLT 结构来完成它。

<newsItem>
<inlineXml>
<h2>Calendar</h2> 
 <p><strong><span class="dates">June 16-18:</span>National Conference, Denver</strong></p>
 <p><strong><span class="dates">June 19-21:</span>Local Event, Chicago</strong></p>
<inlineXml>
</newsItem>

这是我的 XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:output method="xml" indent="no"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="h2">
 <h2><xsl:value-of select="normalize-space(.)"/></h2>
 </xsl:template>

 <xsl:template match="p/strong/span">
 <date><xsl:value-of select="."/></date>
 </xsl:template> 

 <xsl:template match="p">
 <p><xsl:value-of select="normalize-space(.)"/></p>
 </xsl:template>

 </xsl:stylesheet>

这是想要的结果:

<newsItem>
<inlineXml>
<h2>Calendar</h2> 
 <p><date>June 16-18:</date>National Conference, Denver</p>
 <p><date>June 19-21:</date>Local Event, Chicago</p>
<inlineXml>
</newsItem>

这可能很简单,但它难倒了我。

谢谢

如果你改变:

<xsl:template match="p">
   <p><xsl:value-of select="normalize-space(.)"/></p>
</xsl:template>

至:

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

你的结果将变成:

<?xml version="1.0"?>
<newsItem>
  <h2>Calendar</h2>
  <p><date>June 16-18:</date>National Conference, Denver</p>
  <p><date>June 19-21:</date>Local Event, Chicago</p>
</newsItem>

这与预期结果非常接近,只是缺少 <inlineXml> 包装器。这是因为没有与之匹配的模板,所以如果你添加:

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

你会得到你想要的结果。


请注意,现在您拥有三个非常相似的模板:

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

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

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

可以合二为一:

<xsl:template match="newsItem | inlineXml | p">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

另请参阅: https://en.wikipedia.org/wiki/Identity_transform

此 XSLT 1.0 样式表 ...

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

 <xsl:output method="html" version="5" encoding="utf-8" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
   <html>
     <head>
       <title>Inline XML</title>
     </head>
     <body>
       <xsl:apply-templates />
     </body>
   </html>
 </xsl:template>

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

<xsl:template match="strong[span/@class='dates']">
  <xsl:apply-templates />
</xsl:template>

<xsl:template match="strong/span[@class='dates']">
  <date>
    <xsl:apply-templates />
  </date>
</xsl:template>

</xsl:stylesheet>

... 将转换此输入文档 ...

<newsItem>
  <inlineXml>
    <h2>Calendar</h2> 
    <p><strong><span class="dates">June 16-18:</span>National Conference, Denver</strong></p>
    <p><strong><span class="dates">June 19-21:</span>Local Event, Chicago</strong></p>
  </inlineXml>
</newsItem>

... 进入此输出 html 页 ...

<!DOCTYPE HTML>
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <title>Inline XML</title>
   </head>
   <body>
      <newsItem>
         <inlineXml>
            <h2>Calendar</h2>
            <p>
               <date>June 16-18:</date>National Conference, Denver
            </p>
            <p>
               <date>June 19-21:</date>Local Event, Chicago
            </p>
         </inlineXml>
      </newsItem>
   </body>
</html>

一些建议

  1. 没有理由受限于 XSLT 1.0,您可以 升级到 XSLT 2.0,甚至在浏览器平台上(由 Saxon 提供 CE).
  2. 如果您的 date 元素是一种微格式, 你应该考虑 html 5 element time.