我正在尝试生成一个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>
,我得到了:
<fileItem>path-to-xml\file.xml<fileItem>
我如何获得<fileItem>path-to-xml\file.xml</fileItem>
?
如何在调用user:ShowFolderFileList()代替'。'时从我的XML中获取“FolderPath-to-List”。到目前为止,它正在运行。
答案 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, ' ')"/>
</file>
<xsl:if test="contains($files, ' ')">
<xsl:call-template name="files">
<xsl:with-param name="files" select="substring-after($files, ' ')"/>
</xsl:call-template>
</xsl:if>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
还有其他几种选择:
看到这个基本上问同样的问题: