在XSLT 1.0中使用Document()函数

时间:2010-05-04 06:11:50

标签: xml xslt

我正在使用.NET代码触发转换,

除非我将“EnableDocumentFunction”属性添加到XSL设置,否则程序会抛出错误说“.. Usage of Document() function is prohibited”,

实际上程序是不可编辑的,是一种只读的...是否可以编辑XSL代码本身,以便我可以使用document()函数??

示例XSL和XML在这里:
示例XML:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
  <xsl:variable name="State_Code_Trn">
    <State In="California" Out="CA"/>
    <State In="CA" Out="CA"/>
    <State In="Texas" Out="TX"/>
    <State In="TX" Out="TX"/>
  </xsl:variable>

  <xsl:template name="testing" match="test_node">
    <xsl:variable name="test_val">
      <xsl:value-of select="."/>
    </xsl:variable>
    <xsl:element name="{name()}">
      <xsl:choose>
      <xsl:when test="document('')/*/xsl:variable[@name='State_Code_Trn']
              /State[@In=$test_val]">
    <xsl:value-of select="document('')/*/xsl:variable[@name='State_Code_Trn']
              /State[@In=$test_val]/@Out"/>
      </xsl:when>
        <xsl:otherwise>
          <xsl:text>Other</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>



示例XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <test_node>California</test_node>
  <test_node>CA</test_node>
  <test_node> CA</test_node>
  <test_node>Texas</test_node>
  <test_node>TX</test_node>
  <test_node>CAA</test_node>
  <test_node></test_node>
</root>

2 个答案:

答案 0 :(得分:2)

此处的document()函数用于访问XSLT文档本身,并提取xsl:variable的内容。在这种情况下,实际上根本不需要使用document()函数。

因为您在此处使用Microsoft.Net,所以您应该能够访问XSLT的msxml扩展函数。实际上,msxml的相关命名空间已在XSLT文档中定义

xmlns:msxsl="urn:schemas-microsoft-com:xslt"

这意味着您将能够使用节点集函数直接访问State_Code_Tran变量中的节点。为此,请尝试将现有的 xsl:choose 功能更改为:

   <xsl:choose>
    <xsl:when test="msxsl:node-set($State_Code_Trn)/State[@In=$test_val]">
     <xsl:value-of select="msxsl:node-set($State_Code_Trn)/State[@In=$test_val]/@Out"/>
    </xsl:when>
    <xsl:otherwise>
     <xsl:text>Other</xsl:text>
    </xsl:otherwise>
   </xsl:choose>

这应该产生以下输出

<root>
<test_node>CA</test_node>
<test_node>CA</test_node>
<test_node>Other</test_node>
<test_node>TX</test_node>
<test_node>TX</test_node>
<test_node>Other</test_node>
<test_node>Other</test_node>
</root>

(请注意,您在原始XML中的某个'CA'之前有一个空格,这就是为什么它以'其他'形式出现。您可能需要添加一些修剪功能来应对此问题。

答案 1 :(得分:2)

除了@Tim-C的回答,您可以使用ext:node-set()扩展函数,其中“ext”前缀与EXSLT名称空间关联:"http://exslt.org/common"

这得到了XslCompiledTransform的支持,并且会使您的XSLT代码更具可移植性,因为EXSLT是扩展函数的标准库。