0

xsl を使用して、指定したフォルダーにある XML ファイルを一覧表示する 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」を取得するにはどうすればよいですか。これまでのところ、それを実行します。

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" />

しかし、 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 プロセッサを入手できます)。

基本的に同じことを尋ねるこの質問を参照してください。

XSLT:特定のディレクトリからファイル名を取得する方法は?

于 2013-09-14T09:08:45.960 に答える