0

我正在尝试生成一个 XML 文件,其中列出了使用 xsl 指定文件夹中的 XML 文件:

XML 文件:

<xml>
   <folder>FolderPath-to-List</folder>
</xml>

预期结果:

<mergeData newRoot="newRoot">
     <fileList>
           <fileItem>path-to-file/file1.xml</fileItem>
           <fileItem>path-to-file/file2.xml</fileItem>
           <fileItem>path-to-file/file3.xml</fileItem>
           <fileItem>path-to-file/file4.xml</fileItem>
     </fileList>
</mergeData>

到目前为止,我可以使用 XSL 和嵌入式脚本/JScipt 函数在当前文件夹中收集文件列表,如下所示:

<xsl:stylesheet version="1.0"  
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="http://tempuri.org/msxsl"
> 

<msxsl:script language="JScript" implements-prefix="user">
<![CDATA[
      var fso = new ActiveXObject("Scripting.FileSystemObject");

      function   ShowFolderFileList(folderspec)   
      {   
         var   f,   f1,   fc,   s;   

         f   =   fso.GetFolder(folderspec);   
         fc   =   new   Enumerator(f.files);

         s   =   '<fileItem>';   
         for   (;   !fc.atEnd();   fc.moveNext())   
         {   
              s   +=   fc.item(); 

            s   +=   '<fileItem>\n<fileItem>';
         }  
      return(s);   
      }   

  ]]>
  </msxsl:script>

  <xsl:template match="/">
      <mergeData newRoot="Activity">
      <fileList>
    <xsl:value-of select="user:ShowFolderFileList('.')"/>
      </fileList>
      </mergeData>
   </xsl:template>
   </xsl:stylesheet>

但结果是代替得到<fileItem>and </fileItem>,我有:

&lt;fileItem&gt;path-to-xml\file.xml&lt;fileItem&gt;

我怎样才能得到<fileItem>path-to-xml\file.xml</fileItem>
如何在调用 user:ShowFolderFileList() 代替“。”时从我的 XML 中获取“FolderPath-to-List”。到目前为止让它运行。

4

1 回答 1

0

首先要注意的是,目前您正在这样做

<xsl:value-of select="user:ShowFolderFileList('.')"/>

当你真的应该这样做以在你的 XML 中使用你的文件路径时

<xsl:value-of select="user:ShowFolderFileList(string(xml/folder/text()))" /> 

注意这里使用“string()”,因为“text()”实际上返回一个文本节点,而不是字符串的数据类型。

其次,当您以这种方式在 XSLT 中使用 javascript 函数时,我相信它们只能返回字符串和数字的简单数据类型。您的函数返回一个字符串,而不是实际的 XML,当您在字符串上使用xsl:value-of时,任何保留符号都将被转义。

现在,你可以有点调皮,做这个

<xsl:value-of select="user:ShowFolderFileList(string(xml/folder/text()))" 
              disable-output-escaping="yes" />

但这不一定被认为是好的做法,因为禁用输出转义并未得到广泛支持(尽管显然它在 Mircosoft 的实现中有效)。

但是,我能想到的唯一其他方法(在 XSLT 1.0 中)是返回一个文件名列表,用新行分隔,然后编写一个递归模板。试试这个 XSLT 作为示例:

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"    
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"  
                xmlns:user="http://tempuri.org/msxsl" 
                exclude-result-prefixes="msxsl user">

   <xsl:output method="xml" indent="yes"/>

   <msxsl:script language="JScript" implements-prefix="user">
      <![CDATA[
      var fso = new ActiveXObject("Scripting.FileSystemObject");

      function   ShowFolderFileList(folderspec)   
      {   
         var   f,   f1,   fc,   s;

         f   =   fso.GetFolder(folderspec);   
         fc   =   new   Enumerator(f.files);

         s="";
         for   (;   !fc.atEnd();   fc.moveNext())   
         {   
              s   +=   fc.item() + "\n";
         }  
      return s;
      }   
      ]]>
   </msxsl:script>

   <xsl:template match="/">
      <mergeData newRoot="Activity">
         <fileList>
            <xsl:call-template name="files">
               <xsl:with-param name="files" select="user:ShowFolderFileList(string(xml/folder/text()))"/>
            </xsl:call-template>
         </fileList>
      </mergeData>
   </xsl:template>

   <xsl:template name="files">
      <xsl:param name="files"/>
      <xsl:if test="normalize-space($files) != ''">
         <file>
            <xsl:value-of select="substring-before($files, '&#13;')"/>
         </file>
         <xsl:if test="contains($files, '&#13;')">
            <xsl:call-template name="files">
               <xsl:with-param name="files" select="substring-after($files, '&#13;')"/>
            </xsl:call-template>
         </xsl:if>
      </xsl:if>
   </xsl:template>
</xsl:stylesheet>

不过,还有其他几个选项:

  1. 不要为此使用 XSLT!
  2. 升级到 XSLT 2.0(Mircosoft 不支持,但您可以为 .Net 获取其他 XSLT 处理器)

看到这个基本上问同样事情的问题:

XSLT:如何从某个目录获取文件名?

于 2013-09-14T09:08:45.960 回答