XSLT:尝试使用完整的XPath执行contains()。为什么这会失败?

时间:2009-09-24 05:56:32

标签: xslt

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="utf-8" />
  <xsl:template match="/">
    <html>
      <body>
        <span>
          <div style="background-color:#000066;color:#EEEEEE;padding:7px">
            <a name="top" style="padding-left:10px;font-size:28pt">Alerting Variables</a>
          </div>
        </span>
        <div style="display:block;padding-left:50px;padding-bottom:10px" class="hbuttons">
          <a href="CoreAlerts.xml">LDMS Alerts</a>
          <a href="ServerManagerAlerts.xml">LDSM Alerts</a>
          <a href="why.html">Why?</a>
          <a href="examples.html">Examples</a>
          <a href="resources.html">Resources</a>
        </div>
        <div style="clear: left;"></div>
        <!-- This is the Table of Contents-->
        <div style="padding:5px">
          <div style="padding:5px;margin-top:10pt;margin-bottom:10pt;font-weight:bold;font-size:20px">Table of Contents - 
          <a style="position:absolute;margin-left:40px" href="PrintPages/PrintAll.html">
            <img border="0" src="images/PrintButton.png" />
          </a></div>
          <div style="font-family:Arial;font-weight:bold;margin-left:30px;font-size:10pt">
            <xsl:if test="contains(identifiers/sectionname/alert/@name, 'Agent Watcher')">
              <a href="#AgentWatcher">Agent Watcher</a>
              <a style="position:absolute;margin-left:40px" href="PrintPages/PrintAW.html">
                <img border="0" src="images/PrintButton.png" />
              </a>
            </xsl:if>
            <ol style="margin-top:5">
              <xsl:for-each select="identifiers/sectionname/alert">
                <xsl:if test="contains(@name, 'Agent Watcher')">
                  <li style="margin-left:10pt;font-size:8pt">
                    <a>
                      <xsl:attribute name="href">#
                      <xsl:value-of select="@name" /></xsl:attribute>
                      <xsl:value-of select="@name" />
                    </a>
                  </li>
                </xsl:if>
              </xsl:for-each>
            </ol>
          </div>
          <div style="font-family:Arial;font-weight:bold;margin-left:30px;font-size:10pt">
            <a href="#Intel vPro">Intel vPro</a>
            <a style="position:absolute;margin-left:40px" href="PrintPages/PrintvPro.html">
              <img border="0" src="images/PrintButton.png" />
            </a>
            <ol style="margin-top:5">
              <xsl:for-each select="identifiers/SectionName/alert">
                <xsl:if test="contains(@name, 'Intel vPro')">
                  <li style="margin-left:10pt;font-size:8pt">
                    <a>
                      <xsl:attribute name="href">#
                      <xsl:value-of select="@name" /></xsl:attribute>
                      <xsl:value-of select="@name" />
                    </a>
                  </li>
                </xsl:if>
              </xsl:for-each>
            </ol>
          </div>
        </div>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

以上是我的代码示例。

第一个xsl:if语句始终失败,并且从不显示“代理观察器”文本或“打印我”按钮。即使该部分填写在XML中。如果该部分存在,则第一个xsl:if语句失败,但xsl:for-each中包含的第二个语句显示内容。我该如何让它发挥作用。

我想让它包含在内,以便如果XML在该部分中有内容,它会将其放置,但如果不是,它将不是带有标题的空内容,反之亦然。附加样本XML以进行处理。

<identifiers>
  <sectionname>
    <alert name="Agent Watcher Service Startup"></alert>
    <alert name="Agent Watcher Service Not Started"></alert>
    <alert name="Agent Watcher Service Uninstalled"></alert>
    <alert name="Agent Watcher File Deleted"></alert>
  </sectionname>
  <sectionname>
    <alert name="Intel vPro agentless discovery failure"></alert>
    <alert name="Intel vPro System Defense Remediation Alert"></alert>
    <alert name="Intel vPro Enhanced System Defense Remediation Alert"></alert>
    <alert name="Intel vPro Enhanced System Defense Alert"></alert>
  </sectionname>
</identifiers>
  

块引用

1 个答案:

答案 0 :(得分:1)

我还有其他一些建议,但是在我继续之前你需要发布整个(相关的)XSLT。至少需要封闭模板。

编辑:以下是我的样式表提案:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:tmp="http://tempuri.org"
  exclude-result-prefixes="tmp"
>
  <tmp:config>
    <tmp:alert label="Agent Watcher" link="PrintPages/PrintAW.html" />
    <tmp:alert label="Intel vPro" link="PrintPages/PrintvPro.html" />
  </tmp:config>

  <xsl:variable name="everyAlert" select="
    /identifiers/sectionname/alert
  " />

  <xsl:template match="/">
    <html>
      <body>
        <!-- 8< snip -->
        <div style="...">
          <div style="...">
            <xsl:text>Table of Contents - </xsl:text>
            <a style="..." href="PrintPages/PrintAll.html">
              <img border="0" src="images/PrintButton.png" />
            </a>
          </div>
          <xsl:for-each select="document('')/*/tmp:config/tmp:alert">
            <xsl:call-template name="section" />
          </xsl:for-each>
        </div>
      </body>
    </html>
  </xsl:template>

  <xsl:template name="section">
    <xsl:variable name="this" select="." />
    <xsl:variable name="alerts" select="
      $everyAlert[contains(@name, $this/@label)]
    " />

    <xsl:if test="$alerts">
      <div style="...">
        <a href="#{translate($this/@label, ' ', '_')}">
          <xsl:value-of select="$this/@label" />
        </a>
        <a style="..." href="{$this/@link}">
          <img border="0" src="images/PrintButton.png" />
        </a>
        <ol style="...">
          <xsl:for-each select="$alerts">
            <li style="...">
              <a href="#{@name}"><xsl:value-of select="@name" /></a>
            </li>
          </xsl:for-each>
        </ol>
      </div>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

主要特点:

  • 通过命名模板有效地重用代码
  • 打印部分可轻松配置
  • 使用<xsl:text>元素来避免输出中不需要的空格,同时保留正确格式化XSLT代码的自由
  • 使用属性文字符号(花括号{})代替详细<xsl:attribute>元素
  • 使用临时命名空间来允许在样式表本身中存储配置数据
  • 使用<xsl:for-each>循环和document()函数来检索和使用该配置数据
  • for-each利用上下文传输当前@label@link,因此不需要<xsl:param><xsl:template name="section">tmp:config/tmp:alert中运行上下文,而不是sectionname/alert上下文!)
  • 使用全局变量($everyAlert)存储所有节点供以后使用