我想在我的XSLT文件中使用嵌入式资源,但在调用'document(...)'时,C#抱怨“加载文档时出错...”
我想在XSLT文件中使用已定义的资源并通过它来获取它们:“document('')/ / my:resources / ”...
我该怎么做?
ex xsl:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="xslt-gruper-v1.2.xsl" exclude-result-prefixes="my">
<my:resources>
<one>tryb</one>
</my:resources>
<xsl:variable name="res" select="document('')/*/my:resources/("/>
</xsl:stylesheet>
如何在C#中无异常地访问此类结构?我将在静态转换期间通过ex添加。 Opera一切正常。
答案 0 :(得分:10)
<xsl:variable name="res" select="document('')/*/my:resources/("/>
select
属性的值不是语法正确的XPath表达式。每个兼容的XSLT处理器都必须引发错误。
<强>解决方案强>:
将上述内容改为:
<xsl:variable name="vRes" select="document('')/*/my:resources"/>
如果仍有异常,请阅读XsltSettings类。
然后使用this constructor创建一个XsltSettings 实例,如下所示:
XsltSettings(true, false)
不启用脚本 - 将构造函数的第二个参数保留为false
。
以下是更完整的代码段:
// Create the XsltSettings object with document() enabled and script disabled.
XsltSettings settings = new XsltSettings(true,false);
// Create the XslCompiledTransform object and load the style sheet.
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load("sort.xsl", settings, new XmlUrlResolver());
更新:出现错误的另一个可能原因是在内存中动态创建XSLT样式表(不是来自文件)。在这种情况下,XSLT处理器通常无法解析document('')
中的相对uri。
在最后一种情况下,解决方案是使有用元素成为xsl:variable
的内容,并使用xxx:node-set()
扩展函数来处理此元素。
答案 1 :(得分:0)
在整整一天半的时间里梳理头发后,我终于想出了解决同一问题的方法。
我的代码:
NUnit测试:
[Test]
public void Transform_WhenXslUsesTheDocumentFunction_DoesNotThrow()
{
//Arrange
string testOutputPath = GetTestOutputPath(
nameof(Transform_WhenXslUsesTheDocumentFunction_DoesNotThrow)
);
string inputXsl = TestFilePaths.GetResource("Import\\DocumentImporter.xsl");
XsltSettings xsltSettings = new XsltSettings(true, true);
XmlUrlResolver resolver = new XmlUrlResolver();
XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
xslCompiledTransform.Load(inputXsl, xsltSettings, resolver);
//Act
TestDelegate testDelegate = () => xslCompiledTransform.Transform(
TestFilePaths.MinimumValidXml
, testOutputPath
);
//Assert
Assert.DoesNotThrow(testDelegate);
}
DocumentImporter.xsl:
<?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:variable name="DocumentPath" select="'./Document.xml'"/>
<xsl:variable name="DocumentXML" select="document($DocumentPath)"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:value-of select="$DocumentXML//Message"/>
</xsl:template>
</xsl:stylesheet>
Document.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Message>Document Message</Message>
最终我找到了:
https://github.com/dotnet/runtime/issues/26969
通知我我需要使用一个新的.Net Core“功能”,该功能允许我使用代码段使用外部xml文档:
AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
有效的最终代码:
[Test]
public void Transform_WhenXslUsesTheDocumentFunction_DoesNotThrow()
{
AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
//Arrange
string testOutputPath = GetTestOutputPath(
nameof(Transform_WhenXslUsesTheDocumentFunction_DoesNotThrow)
);
string inputXsl = TestFilePaths.GetResource("Import\\DocumentImporter.xsl");
XsltSettings xsltSettings = new XsltSettings(true, true);
XmlUrlResolver resolver = new XmlUrlResolver();
XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
xslCompiledTransform.Load(inputXsl, xsltSettings, resolver);
//Act
TestDelegate testDelegate = () => xslCompiledTransform.Transform(
TestFilePaths.MinimumValidXml
, testOutputPath
);
//Assert
Assert.DoesNotThrow(testDelegate);
}