2011-02-04 110 views
1

我正在使用.NET4代码触发转换。xslt中的文档功能

改造工作得很好,当我写与文档功能的XPath直接在XSLT(见元素PanelOK的例子XSLT):

但当XPATH本身存储在一个变量,它将无法正常工作(见元素PanelException):

<xsl:value-of select="@Customer"/> 

其中@Customer的值为 “文件( 'myXml.xml')/ COM:根/ COM:全球/ @客”

然后我用脚本扩展我的xslt。当我没有在xpath中使用文档功能时,这可以正常工作,例如只/ COM:root/COM:Global/@ Customer。但是对于文档函数,我得到异常由于未知函数,此查询需要XsltContext。

下面是一些示例:xml1具有包含xpath表达式的值的属性customer,xml2是可以找到值的文件,xslt是转换xml1并评估存储在属性中的xpath表达式的转换客户应使用自定义脚本在xml2中查找值,然后在select语句中执行excation。我必须做些什么才能做到这一点?

XML1:

<?xml version="1.0" encoding="UTF-16" standalone="no"?> 
<SFK:root xmlns:SFK="http://www.Test.com/SoftKeys"> 
    <SFK:Panel Customer="document('setting.xml')/COM:root/COM:Global/@Customer"> 
    </SFK:Panel> 
</SFK:root> 

XML2:

<?xml version="1.0" encoding="UTF-16" standalone="no"?> 
<COM:root xmlns:COM="http://www.Test.com/Comm"> 
    <COM:Global Customer="Microsoft"> 
    </COM:Global> 
</COM:root> 

XSLT:

<?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" 
       xmlns:dyn="http://exslt.org/dynamic" 
       xmlns:SFK="http://www.Test.com/SoftKeys" 
       xmlns:COM="http://www.Test.com/Comm" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       extension-element-prefixes="dyn msxsl" 
       exclude-result-prefixes="msxsl xsl SFK COM dyn"> 

    <!--Script to evaluate a string xPath to a Node. the real evaluate extension is not implemented in MS xslt processor--> 
    <msxsl:script implements-prefix="dyn" language="C#"> 
     <![CDATA[ 
      public XPathNodeIterator evaluate(XPathNavigator context, string expression) 
      { 
       XmlNamespaceManager mngr = new XmlNamespaceManager(new NameTable()); 
       mngr.AddNamespace("SFK","http://www.Test.com/SoftKeys"); 
       mngr.AddNamespace("COM","http://www.Test.com/Comm"); 
       mngr.AddNamespace("msxsl","urn:schemas-microsoft-com:xslt"); 

       return context.Select(expression,mngr); // here occurs the exception 
      } 
     ]]> 
    </msxsl:script> 

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="current()/SFK:root/SFK:Panel"/> 
    </xsl:template> 
    <xsl:template match="SFK:Panel"> 
     </PanelOk> 
      <xsl:value-of select="document('xml2.xml')/COM:root/COM:Global/@Customer"/> 
     </PanelOk> 
     </PanelException> 
      <xsl:value-of select="dyn:evaluate(., @Customer)"/> 
     </PanelException>  
    </xsl:template> 
</xsl:stylesheet> 
+0

好问题,+1。请参阅我的答案以解释为什么在没有扩展的情况下这是不可能的,而对于今天的.NET xslt处理器则完全不可能。解决方法是可能的,如果您表示您对此感兴趣 - 可能会提出一个新问题并将其定义为尽可能具体 - 我将很乐意提供此类解决方法。 – 2011-02-04 17:01:52

回答

1

恐怕document功能没有在XPath规范中定义的,因此在无法使用XPath 1.0实现,如Microsoft的XPathNavigator。 document函数仅在XSLT中定义。

我不确定要建议什么,使用Saxon 9或XQSharp,您可以使用XPath 2.0 doc函数,但我不确定您是否希望从.NET Framework的内置XSLT和XPath 1.0实现迁移到第三方XSLT和XPath 2.0实现。

1

EXSLT函数dyn:evaluate未在Microsoft XSLT处理器中实现。

如果希望的XPath表达式的不同部分用xml1的单独元素/属性编码,则可以解决此问题。

当然,这是一个非常有限的解决方案,需要约定和纪律。

即使在XSLT 2.0/XPath2.0中也不支持动态评估XPath表达式。这种支持可能在更高版本中提供,但3.0版本仍具有“工作草案”状态。