2013-09-13 2 views
0

Я пытаюсь сгенерировать XML-файл, который перечислять XML-файлы, которые находятся в указанной папке с помощью XSL:Формат вывода XML без HTML тега с помощью XSL

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>?
Как я могу получить «FolderPath-to-List» из моего XML, который будет использоваться при вызове пользователя: ShowFolderFileList() вместо '.' пока это не работает.

ответ

0

Прежде всего следует отметить, что в том, что в настоящее время вы делаете это

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

Когда на самом деле вы должны делать это, чтобы использовать свой путь к файлу в вашем XML

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

Обратите внимание на использование «string()» здесь, потому что «text()» фактически возвращает текстовый узел, а не тип данных строки.

Во-вторых, когда вы используете функции javascript в XSLT таким образом, я считаю, что они могут возвращать только простые типы данных строки и числа. Ваша функция возвращает строку, а не фактический XML, когда вы используете xsl: значение в строке, любые зарезервированные символы будут экранированы.

Теперь, вы можете быть немного озорной и сделать это

<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 не поддерживает его, но вы можете получить другие процессоры XSLT.Net)

Смотрите этот вопрос, который в основном спрашивает то же самое:

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

+1

Это можно создать ('новый ActiveXObject ('Msxml2.DOMDocument.3.0')') и возвращает MSXML DOM в функции расширения, чтобы вы могли просто использовать префикс '' в XSLT. Они только сложны в том, что существуют различные версии MSXML (MSXML 3, 4, 6)), и я думаю, вам нужно убедиться, что сценарий создает документ DOM той же версии MSXML, используемой для запуска XSLT. Если вы хотите запустить XSLT внутри IE, вам необходимо передать 'system-property ('msxsl: version')', поскольку разные версии IE используют разные версии MSXML. –

Смежные вопросы