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

时间:2013-09-13 20:33:29

标签: javascript xslt xslt-1.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></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”。到目前为止,它正在运行。

1 个答案:

答案 0 :(得分:0)

首先要注意的是,目前你正在做这个

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

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

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

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

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

现在,你可能有点顽皮并且这样做

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

但这并不一定被视为良好做法,因为 disable-output-escaping 并未得到广泛支持(尽管显然它可以在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处理器)
  3. 看到这个基本上问同样的问题:

    XSLT: How to get file names from a certain directory?