使用 XSL 格式化不带 HTML 标记的 XML 输出

Format XML output without HTML tag using XSL

本文关键字:XML 输出 HTML XSL 格式化 使用      更新时间:2023-09-26

我正在尝试生成一个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></fileItem>,我有:

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

我怎样才能得到<fileItem>path-to-xml'file.xml</fileItem>
到目前为止,我如何从我的XML中获取"FolderPath-to-List"以代替"."以使其运行。

首先要注意的是,您目前正在执行此操作

<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:如何从某个目录中获取文件名?