用于输出子元素的XSLT模板

时间:2017-05-25 15:35:42

标签: xml xslt

我遇到了XSLT问题,需要帮助。我用这个替换了原来的帖子。 我有一个带有空元素的XML文件,我最终希望使用第二个XML文件中的内容进行扩展。我在Ubuntu上使用xsltproc(XSLT 1.0)作为我的处理引擎。

我注意到身份模板没有从输入中复制DOCTYPE,如果应该的话。

我创建了一个简化的测试输入文件和简化的XSLT文件。我仍然无法获得“流派”XSLT模板做任何事情。我更改了该模板以删除指定的元素 - 但它没有这样做。

新输入XML -

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE tellico PUBLIC '-//Robby Stephenson/DTD Tellico V11.0//EN' 'http://periapsis.org/tellico/dtd/v11/tellico.dtd'>

<tellico xmlns="http://periapsis.org/tellico/" syntaxVersion="11">
      <collection title="My Videos" type="3">

<entry id="1002">
<title>Midsomer Murders -- Set 25</title>
<id>1002</id>
<comments>Includes bonus material</comments>
<year>2013</year>
<cover>file:///data/www/htdocs/videodb/cache/img/1002.jpg</cover>
<running-time>90</running-time>
<medium>DVD</medium>
<genres></genres>
<set>Yes</set>
<count>3</count>
<location>2</location>
</entry>

</collection>
</tellico>

新的XSLT转换文件 -

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

  <!-- the identity template (copies your input verbatim) -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <!-- special templates only for things that need them -->
  <xsl:template match="genres"/>


</xsl:stylesheet>

处理命令:

xsltproc -o merged.xml --novalid Identity.xslt test-input-merge.xml

我必须使用--novalid选项,因为此时periapsis.org网站已关闭。

我得到的输出是:

<?xml version="1.0"?>
<tellico xmlns="http://periapsis.org/tellico/" syntaxVersion="11">
      <collection title="My Videos" type="3">

<entry id="1002">
<title>Midsomer Murders -- Set 25</title>
<id>1002</id>
<comments>Includes bonus material</comments>
<year>2013</year>
<cover>file:///data/www/htdocs/videodb/cache/img/1002.jpg</cover>
<running-time>90</running-time>
<medium>DVD</medium>
<genres/>
<set>Yes</set>
<count>3</count>
<location>2</location>
</entry>

</collection>
</tellico>

根据XSLT转换,我的理解有限 - “genres”元素应该没有包含在输出中,但它是。现在,这只是一个测试,试图弄清楚如何让类型模板做某事。

我希望这可以改善我原来的帖子,有人看到了什么问题。 感谢所有人提供的任何帮助。

2 个答案:

答案 0 :(得分:1)

match="entry[genres]"表示匹配的元素 里面有entry genres

因此,此模板处理整个entry元素(不是genres)。

结果是什么? 我使用您的XML和XSLT进行了测试并得到了:

<?xml version="1.0" encoding="ISO-8859-1"?>
    Genre data goes here

所以这个模板只输出它的内容, 而不是整个来源,身份模板没有机会 处理任何事情。

可能你应该写match="entry/genres"。 或者只是match="genres"就足够了?

修改

您的模板无效的真正原因是您忘了 关于名称空间问题,即namespace声明 根标签。

它导致:

  • 所有标签都在上面提到的命名空间中,而不是在 默认(空)命名空间,
  • 您的模板尝试在空格中匹配genres元素 命名空间即可。

因此,您可以在源XML中保留属性,包括namespace, 但是在XSLT中进行以下更改:

  • stylesheet标记必须包含此命名空间的声明 带有一些前缀,例如xmlns:tel="http://periapsis.org/tellico/"
  • 模板中的match属性必须引用此内容 命名空间,即包含上述前缀: <xsl:template match="tel:genres"/>

DOCTYPE行而言:

使用 xsltransform.net 我试图将此行包含在源XML中 但得到了以下错误:

Error on line 1 column 2 of http://periapsis.org/:
  SXXP0003: Error reported by XML parser: The markup declarations
  contained or pointed to by the document type declaration must
  be well-formed.

可能原因是所引用的 .dtd 文件中无法访问或出现一些错误。 所以我同意你的意见,这一行应该删除。

答案 1 :(得分:1)

我不知道为什么match="entry[genres]"entry元素不匹配,但无论如何它都是错误的。你需要的是:

<xsl:template match="genres">
  <xsl:copy-of select="document($with)"/>
</xsl:template>