在嵌入式 C# 代码中获取 XSLT 样式表的文件路径? (MSXML)

Get filepath of XSLT stylesheet in embedded C# code? (MSXML)

我使用 XSLT + C# 代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:local="urn:local"
                extension-element-prefixes="msxsl"
                exclude-result-prefixes="msxsl local">

  <msxsl:script language="CSharp" implements-prefix="local">
    <![CDATA[
      public string imageList;

      public bool loadImageList()
      {
        imageList = System.IO.File.ReadAllText("C:\Users\me\Project\images.txt");
        return true;
      }

      public bool inImageList(string str)
      {
        return imageList.Contains("\r\n" + str + "\r\n");
      }
    ]]>
  </msxsl:script>

  <xsl:variable name="loadImageList" select="local:loadImageList()"/>

  <xsl:template match="/">
    <xsl:apply-templates select="recordList/record"/>
  </xsl:template>

  <xsl:template match="record">
    <xsl:if test="inImageList(@id) = true()">
      <image>
        <xsl:value-of select="concat(@id, '.jpg')"/>
      </image>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

在 C# 中,加载外部文件并将内容存储在变量中。函数 inImageList() 提供了测试文本中是否包含特定值的方法。它由 XSLT 代码调用以进行条件代码执行(有效)。

我的问题:我不想硬编码文件路径 C:\Users\me\Project\images.txt,而是想提供一个路径/文件名相对于 .xslt 文件.\images.txt 不起作用,它会在某些 Visual Studio 目录中查找。

是否有函数、system-属性 或任何其他方法来找出我的 .xslt 文件的绝对路径?

在一般情况下,XSLT 片段不需要具有特定位置。虽然它可以存储在文件中,但也可以是网络流,可以嵌入到 XML 文档中等等。所以在 XSLT 中没有可以查询的 "my own location" 的概念。

但是,由于我假设您使用 XslCompiledTransform class 来执行转换,您可以在那里注入一个参数(有关详细信息,请参阅 MSDN)并将其传递给您的loadImageList 函数。

假设样式表可以通过基本 URI 可用的方式加载,您可以按如下方式进行:

<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 mf"
                xmlns:mf="http://example.com/mf"
>
    <xsl:output method="xml" indent="yes"/>

  <msxsl:script language="C#" implements-prefix="mf">
    public string GetBaseUri(XPathNavigator node) {
      return node.BaseURI;
    }

    public string GetFilePath(string baseUri, string fileName) {
      return new Uri(new Uri(baseUri), fileName).LocalPath;
    }
  </msxsl:script>


  <xsl:template match="/">
    <xsl:value-of select="mf:GetFilePath(mf:GetBaseUri(document('')), 'textInput.txt')"/>

  </xsl:template>
</xsl:stylesheet>

请注意,这需要同时启用脚本和 document 函数,然后在 XSLT 内部 document('') 可用于获取样式表的树形表示,然后您可以通过扩展函数采用 XPathNavigator 允许你读出 BaseURI 属性,一旦你有了它,你可以使用 Uri class 来解析相对于该基本 URI 的文件名,然后您可以获得该 URI 的 LocalPath 表示,然后您可以使用它来加载文本文件。

因此,在您的代码上下文中,您可以使用

  public bool loadImageList(string baseUri)
  {
    imageList = System.IO.File.ReadAllText(GetFilePath(baseUri, "images.txt"));
    return true;
  }

  public bool inImageList(string str)
  {
    return imageList.Contains("\r\n" + str + "\r\n");
  }

    public string GetBaseUri(XPathNavigator node) {
      return node.BaseURI;
    }

    public string GetFilePath(string baseUri, string fileName) {
      return new Uri(new Uri(baseUri), fileName).LocalPath;
    }
]]>

 <xsl:variable name="loadImageList" select="local:loadImageList(local:GetBaseUri(document('')))"/>