XSLT:如何从某个目录获取文件名?

时间:2023-02-06 10:51:23

Is there a function in XSLT that can takes in a directory path and gives back all the files in it??

XSLT中是否有一个函数可以接收目录路径并返回其中的所有文件?

I have a xml file now reads like this

我现在有一个xml文件,读起来是这样的

<filelist>
    <file>fileA.xml</file>
    <file>fileB.xml</file>
</filelist>

Now, there's directory called dir, has files fileX.xml, fileY.xml and a bunch of other xml files in it. I want to add these files on to the orginal xml file, so that I can get:

有一个目录叫dir,有文件fileX。xml,fileY。xml和其他一些xml文件。我想把这些文件添加到原始xml文件中,这样我就可以得到:

<filelist>
    <file>fileA.xml</file>
    <file>fileB.xml</file>
    <file>fileX.xml</file>
    <file>fileY.xml</file>
    .... <!-- other files -->
</filelist>

Is there an XSLT way to do this?? something that takes in a dir root, and is able to iterator through all of the files in it?? And then I could just call something like:

有没有XSLT的方法来实现这一点?它包含一个目录根,并且能够遍历其中的所有文件?然后我可以把它叫做

<xsl:element name = file >
     <xsl:copy> <!--whatever file name--> <xsl:copy>
</xsl:element>0

[Edit-solution]

all of the answers were very helpful. I ended up finding an external solution (using saxon). I thought it may be helpful for other people to post my solution here, although it is very specific to my own situation.

所有的答案都很有帮助。最后我找到了一个外部解决方案(使用saxon)。我认为其他人在这里发布我的解决方案可能会有帮助,尽管它非常具体地针对我自己的情况。

I use Ant to build a java web app and need to translate some xml files before deployment. Hence, I was using the xslt task to do the job by adding the "saxon9.jar" in the classpath. And in my xsl file, I just did something like this:

我使用Ant构建java web应用程序,需要在部署之前翻译一些xml文件。因此,我使用xslt任务通过添加“saxon9”来完成这项工作。jar”在类路径中。在我的xsl文件中,我做了如下操作:

<xsl:for-each select="collection('../dir/?select=*.xml')" >
     <xsl:element name='file'>
        <xsl:value-of select="tokenize(document-uri(.), '/')[last()]"/>
     </xsl:element>
</xsl:for-each>

4 个解决方案

#1


4  

XSLT has nothing built-in for this task. XSLT is a transformation language - for dynamic output you generally need a transformation source that contains everything already (just in a different form) – you cannot create XML from nothing.

XSLT没有内置此任务。XSLT是一种转换语言——对于动态输出,您通常需要一个包含所有内容的转换源(只是以不同的形式)——您不能凭空创建XML。

The three ways you can tackle the problem are:

解决这个问题的三种方法是:

  1. Build the XML in a programming language, leaving out XSLT altogether. This is the simplest way to get the result you want.
  2. 用编程语言构建XML,完全排除XSLT。这是得到您想要的结果的最简单的方法。
  3. Build an XSL stylesheet that accepts a parameter, put a (pre-built) delimited list of files into that parameter, let the XSLT handle the string and make XML from it. This involves external handling as well, basically this is option 1., plus you'd have to write an XSL stylesheet that does string handling (something that XSL has not been geared to)
  4. 构建一个接受参数的XSL样式表,将(预构建的)带分隔符的文件列表放入该参数中,让XSLT处理字符串并从中生成XML。这涉及到外部处理,基本上这是选项1。,此外,您还需要编写一个XSL样式表,该样式表可以进行字符串处理(XSL没有对这些进行过调整)
  5. Use extension functions and do the directory processing from within the XSL. An example how to get started can be found in my answer to this question. This is not very portable as extension functions are platform specific.
  6. 使用扩展函数并在XSL中进行目录处理。在我对这个问题的回答中可以找到一个如何开始的例子。这并不是很容易移植,因为扩展功能是特定于平台的。

It boils down to this:

它可以归结为:

  • You will need help from an external programming language
  • 您将需要外部编程语言的帮助
  • You do not absolutely need XSLT do accomplish the task, since XML output is all you need and no transformation is required.
  • 您不需要XSLT来完成这个任务,因为您只需要XML输出,不需要任何转换。

Ergo: Don't use XSL for this.

Ergo:不要为此使用XSL。

#2


1  

You can't do that in native XSLT, but various implementations allow you to add extensions to the functionality.

在本机XSLT中不能这样做,但是各种实现允许向功能添加扩展。

For example, in C# you can add a user defined URN:

例如,在c#中,您可以添加一个用户定义的URN:

 <xsl:stylesheet {snipped the usual xmlns stuff}
    xmlns:user="urn:user" >

then use the functions within "user"

然后使用“user”中的函数

  <xsl:value-of select="user:getdirectory( @mydir )" />

within the C# you associate "user" to a C# class:

在c#中,您将“用户”与c#类关联:

 XSLThelper xslthelper      = new XSLThelper( );  // your class here
 xslArgs.AddExtensionObject( "urn:user", xslthelper );

and your class defines the "getdirectory" function:

类定义“getdirectory”函数:

public class XSLThelper
{
public string getdirectory(System.Xml.XPath.XPathNavigator xml, string strXPath, string strNULL)
{
       //blah
    }
}

Hugh amount of homework left here! MSDN Resource

剩下的家庭作业太多了!MSDN资源

#3


1  

The Q is six years old and answered. Just throwing my 2 cents in for those who land here again.

这个问题的答案是六岁。只是把我的2美分扔给那些在这里的人。

I've needed an XML file representing the filenames in a directory. I've done it three ways:

我需要一个表示目录中的文件名的XML文件。我用了三种方法:

  1. XSLT 2.0 document() as others have pointed out in this thread. Drawback is performance as it reads the file into the dom parser, when all you really wanted is the name. Also as LarsH pointed out in the OP comments, this works only with valid XML files. If you have a non-xml or malformed xml file in the recurse, it crashes the transform.

    正如其他人在本文中指出的,XSLT 2.0文档()。当它将文件读入dom解析器时,缺点是性能,当您真正需要的是名称时。正如LarsH在OP注释中指出的,这只适用于有效的XML文件。如果在递归中有一个非xml或格式错误的xml文件,那么它会崩溃转换。

  2. The tool xmlstarlet with the command xmlstarlet ls > filenames.xml

    使用xmlstarlet命令的工具xmlstarlet ls >文件保护。xml

  3. A crude bash script I made up (it could be optimized):

    我编造了一个粗糙的bash脚本(可以对其进行优化):

DIRECTORY=$1
RESULTFILE=$2

# put the directory listing into a temp file
# modify the ls command for your needs
ls -A1 $DIRECTORY > /tmp/zFiles.txt

# remove detritus and wrap the lines in <file> elements
sed -i -e's/^[^$]*$/   <file filename="&"\/>/' /tmp/zFiles.txt

# build the file
echo '<?xml version="1.0" encoding="UTF-8"?>' > $RESULTFILE
echo "<files>" >> $RESULTFILE
cat /tmp/zFiles.txt >> $RESULTFILE
echo "</files>" >> $RESULTFILE

I had used the bash script for a long time but now I use the xmlstarlet method exclusively. The result starlet file contains specific file attributes such as permissions and dates, I have found that helpful.

我已经使用bash脚本很久了,但是现在我只使用xmlstarlet方法。结果starlet文件包含特定的文件属性,如权限和日期,我发现这很有帮助。

#4


0  

You should be able to use the document() function to read the XML files in. I'm not sure how well it is supported on various XSLT engines though.

您应该能够使用document()函数来读取其中的XML文件。但我不确定它在各种XSLT引擎上的支持程度。

This is a good example showing it in use.

这是一个很好的例子,展示了它的使用。

But that doesn't address the problem of reading in the names of the files from the directory. The other answer gives a way of doing that side of it.

但这并没有解决从目录中读取文件名称的问题。另一个答案给出了一种方法。

#1


4  

XSLT has nothing built-in for this task. XSLT is a transformation language - for dynamic output you generally need a transformation source that contains everything already (just in a different form) – you cannot create XML from nothing.

XSLT没有内置此任务。XSLT是一种转换语言——对于动态输出,您通常需要一个包含所有内容的转换源(只是以不同的形式)——您不能凭空创建XML。

The three ways you can tackle the problem are:

解决这个问题的三种方法是:

  1. Build the XML in a programming language, leaving out XSLT altogether. This is the simplest way to get the result you want.
  2. 用编程语言构建XML,完全排除XSLT。这是得到您想要的结果的最简单的方法。
  3. Build an XSL stylesheet that accepts a parameter, put a (pre-built) delimited list of files into that parameter, let the XSLT handle the string and make XML from it. This involves external handling as well, basically this is option 1., plus you'd have to write an XSL stylesheet that does string handling (something that XSL has not been geared to)
  4. 构建一个接受参数的XSL样式表,将(预构建的)带分隔符的文件列表放入该参数中,让XSLT处理字符串并从中生成XML。这涉及到外部处理,基本上这是选项1。,此外,您还需要编写一个XSL样式表,该样式表可以进行字符串处理(XSL没有对这些进行过调整)
  5. Use extension functions and do the directory processing from within the XSL. An example how to get started can be found in my answer to this question. This is not very portable as extension functions are platform specific.
  6. 使用扩展函数并在XSL中进行目录处理。在我对这个问题的回答中可以找到一个如何开始的例子。这并不是很容易移植,因为扩展功能是特定于平台的。

It boils down to this:

它可以归结为:

  • You will need help from an external programming language
  • 您将需要外部编程语言的帮助
  • You do not absolutely need XSLT do accomplish the task, since XML output is all you need and no transformation is required.
  • 您不需要XSLT来完成这个任务,因为您只需要XML输出,不需要任何转换。

Ergo: Don't use XSL for this.

Ergo:不要为此使用XSL。

#2


1  

You can't do that in native XSLT, but various implementations allow you to add extensions to the functionality.

在本机XSLT中不能这样做,但是各种实现允许向功能添加扩展。

For example, in C# you can add a user defined URN:

例如,在c#中,您可以添加一个用户定义的URN:

 <xsl:stylesheet {snipped the usual xmlns stuff}
    xmlns:user="urn:user" >

then use the functions within "user"

然后使用“user”中的函数

  <xsl:value-of select="user:getdirectory( @mydir )" />

within the C# you associate "user" to a C# class:

在c#中,您将“用户”与c#类关联:

 XSLThelper xslthelper      = new XSLThelper( );  // your class here
 xslArgs.AddExtensionObject( "urn:user", xslthelper );

and your class defines the "getdirectory" function:

类定义“getdirectory”函数:

public class XSLThelper
{
public string getdirectory(System.Xml.XPath.XPathNavigator xml, string strXPath, string strNULL)
{
       //blah
    }
}

Hugh amount of homework left here! MSDN Resource

剩下的家庭作业太多了!MSDN资源

#3


1  

The Q is six years old and answered. Just throwing my 2 cents in for those who land here again.

这个问题的答案是六岁。只是把我的2美分扔给那些在这里的人。

I've needed an XML file representing the filenames in a directory. I've done it three ways:

我需要一个表示目录中的文件名的XML文件。我用了三种方法:

  1. XSLT 2.0 document() as others have pointed out in this thread. Drawback is performance as it reads the file into the dom parser, when all you really wanted is the name. Also as LarsH pointed out in the OP comments, this works only with valid XML files. If you have a non-xml or malformed xml file in the recurse, it crashes the transform.

    正如其他人在本文中指出的,XSLT 2.0文档()。当它将文件读入dom解析器时,缺点是性能,当您真正需要的是名称时。正如LarsH在OP注释中指出的,这只适用于有效的XML文件。如果在递归中有一个非xml或格式错误的xml文件,那么它会崩溃转换。

  2. The tool xmlstarlet with the command xmlstarlet ls > filenames.xml

    使用xmlstarlet命令的工具xmlstarlet ls >文件保护。xml

  3. A crude bash script I made up (it could be optimized):

    我编造了一个粗糙的bash脚本(可以对其进行优化):

DIRECTORY=$1
RESULTFILE=$2

# put the directory listing into a temp file
# modify the ls command for your needs
ls -A1 $DIRECTORY > /tmp/zFiles.txt

# remove detritus and wrap the lines in <file> elements
sed -i -e's/^[^$]*$/   <file filename="&"\/>/' /tmp/zFiles.txt

# build the file
echo '<?xml version="1.0" encoding="UTF-8"?>' > $RESULTFILE
echo "<files>" >> $RESULTFILE
cat /tmp/zFiles.txt >> $RESULTFILE
echo "</files>" >> $RESULTFILE

I had used the bash script for a long time but now I use the xmlstarlet method exclusively. The result starlet file contains specific file attributes such as permissions and dates, I have found that helpful.

我已经使用bash脚本很久了,但是现在我只使用xmlstarlet方法。结果starlet文件包含特定的文件属性,如权限和日期,我发现这很有帮助。

#4


0  

You should be able to use the document() function to read the XML files in. I'm not sure how well it is supported on various XSLT engines though.

您应该能够使用document()函数来读取其中的XML文件。但我不确定它在各种XSLT引擎上的支持程度。

This is a good example showing it in use.

这是一个很好的例子,展示了它的使用。

But that doesn't address the problem of reading in the names of the files from the directory. The other answer gives a way of doing that side of it.

但这并没有解决从目录中读取文件名称的问题。另一个答案给出了一种方法。