xslt仅选择具有给定值的元素

时间:2016-02-21 12:28:58

标签: xslt

这是我的意见:

<div class="z">zzz
  <div class="a">a1</div>
  <div class="b">b1
    <div class="c">b1c1
      <div class="d">b1c1d1</div>
      <div class="e">b1c1e1</div>
      <div class="f">b1c1f1</div>
    </div>
    <div class="c">b1c2
      <div class="d">b1c2d1</div>
      <div class="e">b1c2e1</div>
      <div class="f">b1c2f1</div>
      <div class="f">b1c2f2</div>
    </div>
  </div>
  <div class="b">b2
    <div class="c">b2c1
      <div class="d">b2c1d1</div>
      <div class="e">b2c1e1</div>
      <div class="e">b2c1e2</div>
      <div class="f">b2c1f1</div>
    </div>
  </div>
</div>

这是我想要的输出:

<div class="z">zzz
  <div class="a">a1</div>
  <div class="b">b1
    <div class="c">b1c1
      <div class="d">b1c1d1</div>
      <div class="e">b1c1e1</div>
      <div class="f">b1c1f1</div>
    </div>
    <div class="c">b1c2
      <div class="d">b1c2d1</div>
      <div class="e">b1c2e1</div>
      <div class="f">b1c2f1</div>
      <div class="f">b1c2f2</div>
    </div>
  </div>
</div>

我希望得到:

  • div class =&#34; z&#34;的任何文字,即&#34; zzz&#34;
  • 任何有课程的孩子!=&#34; b&#34;
  • 任何有班级=&#34; b&#34;和值=&#34; b1&#34;

我正在使用以下xslt:

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

 <!-- Identity template, copies everything as is -->
 <xsl:template match="@*|node()">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="div[@class='z']">
   <xsl:apply-templates select="div[@class='b' and text()='b1']" />
 </xsl:template>

</xsl:stylesheet>

但不幸的是我的输出是空的:(

我做错了什么?

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

你遇到的主要问题是&#34; b1&#34;的文本节点。还包含空格。 &#34; b1&#34;之后是换行符和一些空格,这就是您对文本节点的当前检查失败的原因。为了满足这个需求,您可以使用normalize-space函数来修剪末尾的空白(它还会将文本中间的多个空格字符组合到一个空格中,如果存在的话)

 <xsl:apply-templates select="div[@class='b' and normalize-space(text())='b1']" />

这至少会给你一些输出,但你也会找到&#34; z&#34; class div没有出现在输出中。这是因为匹配div后,您必须将节点显式复制到输出,以及所有子节点和属性。目前,你只是选择一个&#34; b&#34;类的div,而不是其他任何东西。

因此,您的xsl:apply-templates应该看起来像这样:

<xsl:apply-templates select="@*|text()|div[(@class='b' and normalize-space(text())='b1') or @class != 'b']" />

但是,您可以从不同的角度查看问题。不要为要复制的内容编写规则,而是编写您不想复制的规则,并创建模板以忽略此类节点。身份模板负责复制您想要的所有内容。

请尝试使用此XSLT:

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

 <!-- Identity template, copies everything as is -->
 <xsl:template match="@*|node()">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="div[@class='b' and normalize-space(text())!='b1']" />

</xsl:stylesheet>