当特定模板存在时,不确定为什么要打印所有文本

时间:2017-04-01 13:44:35

标签: xml xslt

我有一个特定于listitems节点的模板元素。

XSL

thingId

XML

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output method="text"/>

  <xsl:template match="listitems">
    <xsl:value-of select="@status" />
  </xsl:template>

</xsl:stylesheet>

结果

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="callvsapply.xslt"?>
<!-- sample XML snippet -->
<xml>
  <foo status="No">You are here.</foo>
  <bar status="Yes">Hello Bar!</bar>
  <baz status="No">Hello Baz!</baz>
  <listitems status="Yes" id="13" />
  <listitems status="No" id="12" />
</xml>

为什么要打印所有文字?我希望只有是和否。

2 个答案:

答案 0 :(得分:3)

XSLT具有"built-in template rules"的概念,如果没有为应用模板的当前节点定义相关模板,则使用这些模板。

他们看起来像这样:

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

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="processing-instruction()|comment()"/>

归结为:

  • 如果当前节点是元素或根节点,则将模板应用于所有子节点。
  • 如果当前节点是文本节点或属性节点,请将其值放在输出中。
  • 如果当前节点是处理指令或注释,则不执行任何操作。

基本上,如果没有指定模板,XSLT的默认行为是从上到下遍历文档,沿途输出所有文本节点的值。这就是你所看到的 - 你的XSLT正在输出它在下来时遇到的所有文本。

为了解决这个问题,有两种基本方法:

第一种方法:拦截根节点(或文档元素)处的处理,并直接从那里定位要处理的节点:

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

  <xsl:output method="text"/>

  <xsl:template match="/*">
    <xsl:apply-templates select="listitems" />
  </xsl:template>

  <xsl:template match="listitems">
    <xsl:value-of select="@status" />
  </xsl:template>

</xsl:stylesheet>

第二种方法:覆盖文本节点的内置处理,以便默认情况下它们的值不会发送到输出:

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

  <xsl:output method="text"/>

  <xsl:template match="listitems">
    <xsl:value-of select="@status" />
  </xsl:template>

  <xsl:template match="text()" />

</xsl:stylesheet>

答案 1 :(得分:1)

您必须先删除所有不需要打印的元素。

为此您可以使用:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">

        <xsl:output method="text"/>

        <xsl:template match="listitems">
                <xsl:value-of select="@status" />
        </xsl:template>

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

</xsl:stylesheet>