从.NET代码可以直接调用特定的XSLT模板吗? 即通常给出的代码如下: (VB.Net抱歉,这是旧代码!)
Dim xsl As New System.Xml.Xsl.XslCompiledTransform()
xsl.Load(SomeXSLFile)
xsl.Transform(SomeXML, SomeArgs, SomeOutput)
引擎将根据与XML文档匹配的内容处理XSL文件中的所有模板。
但是作为我的XSL文件的一部分,我有一个命名模板:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:text>Some output</xsl:text>
<xsl:call-template name="Boilerplate"/>
</xsl:template>
<xsl:template name="Boilerplate">
<xsl:text>Generated by XSL</xsl:text>
</xsl:template>
</xsl:stylesheet>
是否有办法直接从.NET代码调用此命名模板(提供文档或假设空文档)
我可以通过在XSL中使用规则来检测特定的XML模式(例如<CallTemplate name="Boilerplate"/>
)并采取相应的行动,但希望有更自然的方法来解决这个问题吗?
答案 0 :(得分:2)
实际上,没有办法直接执行此操作,但可以使用xsl:include或xsl:import创建包含目标样式表的样式表,然后调用命名模板。像这样:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="(your stylesheet)"/>
<xsl:template match="/">
<xsl:call-template name="(template name)"/>
</xsl:template>
</xsl:stylesheet>
我很少使用xsl:include或xsl:import但我真的不能100%确定这是如何工作的,模板匹配可能会有一个优先顺序问题&#34; \&# 34;在这个样式表和你的样式表之间,但希望这能为你指明一个有用的方向。
答案 1 :(得分:0)
与Flynn1179的答案类似,我改为采用现有的XSL文件,将match = / template替换为只调用命名模板的文件。
此代码非常粗糙,应在使用前进行整理。 此外,它假定只传入一个XMLReader,但不检查它。
Private Shared dicStaticTemplateContent As New Dictionary(Of String, String)
Private Shared Function GetStaticTemplateContent(xmrXSLFile As System.Xml.XmlReader, strTemplateName As String) As String
If Not dicStaticTemplateContent.ContainsKey(strTemplateName) Then
Dim xmd As New System.Xml.XmlDocument
xmd.Load(xmrXSLFile)
Dim nsm As New System.Xml.XmlNamespaceManager(xmd.NameTable)
nsm.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform")
Dim xmnRootTemplate As System.Xml.XmlNode = xmd.SelectSingleNode("/xsl:stylesheet/xsl:template[@match='/']", nsm)
Dim xmeNewRoot As System.Xml.XmlElement = xmd.CreateElement("template", "http://www.w3.org/1999/XSL/Transform")
If (xmnRootTemplate Is Nothing) Then
xmnRootTemplate = xmd.SelectSingleNode("/xsl:stylesheet/xsl:template[1]", nsm)
If (xmnRootTemplate Is Nothing) Then
xmd.DocumentElement.AppendChild(xmeNewRoot) 'quite pointless actually, if there are no templates then the thing won't work anyway, but this is a shortcut towards providing a somewhat more meaningful error anyway (from the xsl engine)
Else
xmd.DocumentElement.InsertBefore(xmeNewRoot, xmnRootTemplate)
End If
Else
xmnRootTemplate.ParentNode.ReplaceChild(xmeNewRoot, xmnRootTemplate)
End If
xmeNewRoot.InnerXml = "<xsl:call-template name=""" + strTemplateName + """/>"
xmeNewRoot.SetAttribute("match", "/")
Dim xsl As New System.Xml.Xsl.XslCompiledTransform()
Dim xss As New System.Xml.Xsl.XsltSettings(True, True)
xsl.Load(xmd, xss, Nothing)
Dim strResult = ProcessTransform(xmd, xsl, Nothing, Nothing)
dicStaticTemplateContent.Add(strTemplateName, strResult)
End If
Return dicStaticTemplateContent(strTemplateName)
End Function
并非所有代码路径都经过测试(特别是没有匹配= /模板的地方)
另外,请注意模板名称上的注入攻击