在 .NET XSLT 中使用 document() 函数会产生错误

Posted

技术标签:

【中文标题】在 .NET XSLT 中使用 document() 函数会产生错误【英文标题】:using document() function in .NET XSLT generates error 【发布时间】:2021-04-26 01:58:34 【问题描述】:

我想在我的 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 一切正常。

【问题讨论】:

【参考方案1】:
<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

下面是更完整的代码sn-p

// 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 非常好的答案。有时,当document('') 给我带来问题时,我使用 p/2 函数(知道输入的样式表来自同一目录) @Simon:+1 似乎被遗忘了;)。我会加一个,这是一个很好的答案。 我遇到了同样的问题,但我没有看到问题的答案。什么是 p/2 函数?如何使用 Node-set() 作为变量查找? @goroth node-set() 选择作为变量值的临时树——更准确地说,将作为变量值的 RTF(结果树片段)转换为可以操作的普通XPath文档节点。 @DimitreNovaatchev 感谢您提供的信息。我有类似的问题,但有人能够帮助我。 ***.com/questions/27365166/…【参考方案2】:

在扯了一天半的头发之后,我终于找到了解决我所看到的相同问题的方法。

我的代码:

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>

文档.xml:

<?xml version="1.0" encoding="utf-8" ?>
<Message>Document Message</Message>

最终我发现了这个:

https://github.com/dotnet/runtime/issues/26969

通知我我需要使用新的 .Net Core“功能”,这将允许我使用我的外部 xml 文档,使用 sn-p:

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);

【讨论】:

以上是关于在 .NET XSLT 中使用 document() 函数会产生错误的主要内容,如果未能解决你的问题,请参考以下文章

document() 函数在 XSLT 中如何工作?

XML - XSLT - count() 函数内的 document() 函数

在 WebLogic 中使用相对路径调用 xslt document() 函数

XSLT document() 在 WebKit 浏览器中的使用

使用XSLT检索XML文件名

c# / xslt - XmlResolver 未被 document() 函数调用