Previous Up Next


p:directory-list

p:directory-list — Lists the files, directories, and other contents of a directory on the filesystem.

Synopsis

<p:declare-step type="p:directory-list">
     <p:output port="result"/>
     <p:option name="path" required="true"/>                       <!-- anyURI -->
     <p:option name="include-filter"/>                             <!-- RegularExpression -->
     <p:option name="exclude-filter"/>                             <!-- RegularExpression -->
</p:declare-step>

Description

The p:directory-list step lists the contents of the specified directory on the filesystem.

The value of the path option is interpreted as an IRI reference. If it is relative, it is made absolute against the base URI of the element on which it is specified.

The values of the include-filter and exclude-filter options are regular expression as specified in [XPath 2.0 Functions and Operators], section 7.61 “Regular Expression Syntax”.

If the include-filter pattern matches the name of a filesystem object, that object is included in the output. If the exclude-filter pattern matches the name, that object is excluded from the output. If both options are provided, the include filter is processed first, then the exclude filter.

Processors must support directory paths whose scheme is file:; they may also support other schemes, but the semantics of those schemes is implementation-defined.

The “c:directory” document that the p:directory-list step produces lists the included filesystem objects. The base URI of the document is the directory path read; it has a name attribute that is the last segment of the directory path.

The children of the c:directory element represent each of the included filesystem objects:

  • A c:directory is produced for each subdirectory.

  • A c:file is produced for each file.

  • If the filesystem supports “special” objects (devices, links, etc.), those may be represented with c:other elements. Exactly what constitutes “special” is implementation-defined and may vary by platform.

The c:directory-list step does not process subdirectories recursively. For recursive processing, see ex:recursive-directory-list.

Each of the elements c:file, c:directory, and c:other has a name whose value is a relative IRI reference, giving the (local) file or directory name. Implementations may include additional attributes.

Errors

Error Description
err:C0012 Occurs if the step cannot read the specified directory due to access restrictions or if the environment doesn't support the notion of a hierarchical directory structure.
err:C0017 Occurs if the absolute path does not specify a directory.

Examples

What's in my “XProc book” directory? Let's see! (This example pipeline is in a directory a couple of levels below the main book directory, hence the “../..”.)

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                version="1.0">
    
      <p:directory-list path="../.."/>
  5 </p:pipeline>
Output
1 <c:directory xmlns:c="http://www.w3.org/ns/xproc-step"
name="src"
xml:base="file:/projects/xproc/src/">
<c:directory name=".svn"/>
5 <c:file name="bibl.xml"/>
<c:file name="bibl.xml~"/>
<c:file name="book.html"/>
<c:file name="book.html~"/>
<c:file name="book.xml"/>
10 <c:file name="book.xml~"/>
<c:file name="ch01.xml"/>
<c:file name="ch02.xml"/>
<c:file name="ch03.xml"/>
<c:file name="ch04.xml"/>
15 <c:file name="ch04.xml~"/>
<c:file name="ch05.xml"/>
<c:file name="ch05.xml~"/>
<c:file name="ch06.xml"/>
<c:file name="ch06.xml~"/>
20 <c:file name="ch07.xml"/>
<c:file name="ch07.xml~"/>
<c:file name="ch08.xml"/>
<c:file name="ch08.xml~"/>
<c:directory name="compound"/>
25 <c:directory name="core"/>
<c:directory name="examples"/>
<c:directory name="fileutils"/>
<c:file name="glossary.xml"/>
<c:file name="glossary.xml~"/>
30 <c:file name="Makefile"/>
<c:file name="Makefile~"/>
<c:directory name="osutils"/>
<c:file name="schemas.xml"/>
<c:file name="schemas.xml~"/>
35 <c:file name="template.xml"/>
<c:directory name="utils"/>
<c:directory name="x"/>
<c:file name="xc01.xml"/>
<c:file name="xc01.xml~"/>
40 <c:file name="xc02.xml"/>
<c:directory name="xpl"/>
<c:file name="xproc.xpr"/>
</c:directory>

If you only want the XML files, use a filter:

  1 <p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
                version="1.0">
    
      <p:directory-list path="../.." include-filter="^.*\.xml$"/>
  5 </p:pipeline>
Output
1 <c:directory xmlns:c="http://www.w3.org/ns/xproc-step"
name="src"
xml:base="file:/projects/xproc/src/">
<c:file name="bibl.xml"/>
5 <c:file name="book.xml"/>
<c:file name="ch01.xml"/>
<c:file name="ch02.xml"/>
<c:file name="ch03.xml"/>
<c:file name="ch04.xml"/>
10 <c:file name="ch05.xml"/>
<c:file name="ch06.xml"/>
<c:file name="ch07.xml"/>
<c:file name="ch08.xml"/>
<c:file name="glossary.xml"/>
15 <c:file name="schemas.xml"/>
<c:file name="template.xml"/>
<c:file name="xc01.xml"/>
<c:file name="xc02.xml"/>
</c:directory>

A Recursive Directory Listing

The standard p:directory-list step does not build an entire tree, it only returns the contents of a single directory. But it's easy to write your own recursive processor directly in XProc:

  1 <p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
    		xmlns:c="http://www.w3.org/ns/xproc-step"
    		xmlns:cx="http://xmlcalabash.com/ns/extensions"
                    type="cx:recursive-directory-list"
  5                 version="1.0">
      <p:output port="result"/>
      <p:option name="path" required="true"/>
      <p:option name="include-filter"/>
      <p:option name="exclude-filter"/>
 10   <p:option name="depth" select="-1"/>
    
      <p:choose>
        <p:when test="p:value-available('include-filter')
                      and p:value-available('exclude-filter')">
 15       <p:directory-list>
            <p:with-option name="path" select="$path"/>
            <p:with-option name="include-filter" select="$include-filter"/>
            <p:with-option name="exclude-filter" select="$exclude-filter"/>
          </p:directory-list>
 20     </p:when>
    
        <p:when test="p:value-available('include-filter')">
          <p:directory-list>
            <p:with-option name="path" select="$path"/>
 25         <p:with-option name="include-filter" select="$include-filter"/>
          </p:directory-list>
        </p:when>
    
        <p:when test="p:value-available('exclude-filter')">
 30       <p:directory-list>
            <p:with-option name="path" select="$path"/>
            <p:with-option name="exclude-filter" select="$exclude-filter"/>
          </p:directory-list>
        </p:when>
 35 
        <p:otherwise>
          <p:directory-list>
            <p:with-option name="path" select="$path"/>
          </p:directory-list>
 40     </p:otherwise>
      </p:choose>
    
      <p:viewport match="/c:directory/c:directory">
        <p:variable name="name" select="/*/@name"/>
 45 
        <p:choose>
          <p:when test="$depth != 0">
            <p:choose>
              <p:when test="p:value-available('include-filter')
 50                         and p:value-available('exclude-filter')">
                <cx:recursive-directory-list>
                  <p:with-option name="path" select="concat($path,'/',$name)"/>
                  <p:with-option name="include-filter" select="$include-filter"/>
                  <p:with-option name="exclude-filter" select="$exclude-filter"/>
 55               <p:with-option name="depth" select="$depth - 1"/>
                </cx:recursive-directory-list>
              </p:when>
    
              <p:when test="p:value-available('include-filter')">
 60             <cx:recursive-directory-list>
                  <p:with-option name="path" select="concat($path,'/',$name)"/>
                  <p:with-option name="include-filter" select="$include-filter"/>
                  <p:with-option name="depth" select="$depth - 1"/>
                </cx:recursive-directory-list>
 65           </p:when>
    
              <p:when test="p:value-available('exclude-filter')">
                <cx:recursive-directory-list>
                  <p:with-option name="path" select="concat($path,'/',$name)"/>
 70               <p:with-option name="exclude-filter" select="$exclude-filter"/>
                  <p:with-option name="depth" select="$depth - 1"/>
                </cx:recursive-directory-list>
              </p:when>
    
 75           <p:otherwise>
                <cx:recursive-directory-list>
                  <p:with-option name="path" select="concat($path,'/',$name)"/>
                  <p:with-option name="depth" select="$depth - 1"/>
                </cx:recursive-directory-list>
 80           </p:otherwise>
            </p:choose>
          </p:when>
          <p:otherwise>
    	<p:identity/>
 85       </p:otherwise>
        </p:choose>
      </p:viewport>
    
    </p:declare-step>

The slightly convoluted p:choose is a consequence of limitations in how p:value-available works; see Section 3, “p:value-available”.