XSLT loop over a set of files in the directory?

给你一囗甜甜゛ 提交于 2021-02-08 10:38:44

问题


I have a situation where I have a directory full of xsd files that need conversion done to them generate a output file for each of them. I have my stylesheet operating on a single document fine, but I'd like to extend that. Well, for now I haven't using a xslt editor, saxon has installed. here is xslt file:

<xsl:stylesheet version="1.0" 
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            >

<xsl:output method="text"/>

<!--* Ignore anything that looks complicated *-->
<xsl:template match="xsd:attribute 
                   | xsd:attributeGroup
                   | xsd:group
                   | xsd:schema/xsd:element[@type]
                   | xsd:notation
                   | xsd:annotation
                   "/>
<!--* Ignore text nodes (otherwise the output will be
  * inundated with whitespace) *-->

<xsl:template match="text()"/>

 <!--* Top-level elements with local complex types; those
  * we want to handle.
  *-->

<xsl:template match = "xsd:schema/xsd:element[xsd:complexType]">
<xsl:apply-templates/>
  </xsl:template>

  <!--* Aha!  A complex type whose content model we want to turn 
  * into a regular expression 
  *-->

<xsl:template match = "xsd:element/xsd:complexType
                     [xsd:sequence | xsd:choice | xsd:all]">
<!--* write out the name for the named regex *-->
<xsl:value-of select="concat('&#xA;&#xA;',
                      @name, parent::xsd:element/@name, 
                      ' ')"/>
<!--* write out the regex *-->
<xsl:apply-templates/>
</xsl:template>

<!--* Simple recursive case:  we encounter a model group. *-->

<xsl:template match = "xsd:sequence|xsd:choice|xsd:all">
<!--* Parenthesize the group and handle its children. *-->
<xsl:text>(</xsl:text>
<xsl:apply-templates/>
<xsl:text>)</xsl:text>

<!--* Append *, ?, +, or {min, max}. *-->
<xsl:call-template name="occurrence-indicator"/>

<!--* If our parent has further children, 
    * append the appropriate connector. *-->
<xsl:call-template name="connector"/>
</xsl:template>

<!--* An element in a content model. *-->
  <xsl:template match = "xsd:element[ancestor::xsd:complexType]">
<!--* Write out the element's name.  We're lazy so 
    * we don't bother with a QName for a local element.
    * Also, we don't recur. *-->
<xsl:value-of select="concat(@ref, @name)"/>

<!--* Handle occurrence indicator and connect
    * just as for groups. *-->
<xsl:call-template name="occurrence-indicator"/>
<xsl:call-template name="connector"/>
</xsl:template>


<!--* Emit the appropriate occurrence indicator for
  * a group or element.
  * Use {min,max}, {min,}, or {n} notation for 
  * non-standard occurrence counts.
  *-->

<xsl:template name="occurrence-indicator">
<xsl:choose>
  <xsl:when test="(@minOccurs='1' or not(@minOccurs)) 
                  and 
                  (@maxOccurs='1' or not(@maxOccurs))">
    <xsl:text></xsl:text>
  </xsl:when>
  <xsl:when test="@minOccurs='0' 
                  and 
                  (@maxOccurs='1' or not(@maxOccurs))">
    <xsl:text>?</xsl:text>
  </xsl:when>
  <xsl:when test="@minOccurs='0' and @maxOccurs='unbounded'">
    <xsl:text>*</xsl:text>
  </xsl:when>
  <xsl:when test="(@minOccurs='1' or not(@minOccurs)) 
                  and 
                  @maxOccurs='unbounded'">
    <xsl:text>+</xsl:text>
  </xsl:when>
  <xsl:when test="@minOccurs=@maxOccurs">
    <xsl:value-of select="concat('{', @minOccurs,'}')"/>
  </xsl:when>
  <xsl:when test="@maxOccurs='unbounded'">
    <xsl:value-of select="concat('{', @minOccurs,',}')"/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of select="concat('{', 
                          @minOccurs,
                          ',',
                          @maxOccurs,
                          '}')"/>
  </xsl:otherwise>
</xsl:choose>
  </xsl:template>

  <xsl:template name="connector">
<!--* Emit the appropriate connector, if we need one. *-->
<xsl:if test="following-sibling::*[self::xsd:sequence 
              | self::xsd:choice 
              | self::xsd:all 
              | self::xsd:element]">
  <xsl:choose>
    <xsl:when test="parent::xsd:sequence">
      <xsl:text>, </xsl:text>
    </xsl:when>
    <xsl:when test="parent::xsd:choice">
      <xsl:text> | </xsl:text>
    </xsl:when>
    <xsl:when test="parent::xsd:all">
      <xsl:text> &amp; </xsl:text>
    </xsl:when>
  </xsl:choose>
</xsl:if>
  </xsl:template>

</xsl:stylesheet>

回答1:


There are so many ways to do match treatment (bash, vb-scrpt, ...).

I often use ant. Here some examples how to apply XSLT on multiple files in a folder. The ant "build.xml" file running the XSL transformation on all .xsd files in the "destinationFolder":

<?xml version="1.0" encoding="UTF-8"?>
<project name="TransformMultipleFiles" default="transformMulti">
   <property name="xsl_processor.file" value="saxon9he.jar"/>
   <target name="transformMulti">
    <!-- Transform all the files in the directory -->
       <xslt basedir="fileFolder" destdir="destinationFolder" includes="**/*.xsd" extension=".xml" style="yourXSLT.xslt" classpath="${xsl_processor.file}" />
   </target>
</project>

Just add above code into a file named build.xml and run the file with ant by just going into this directory and typing "ant" into the console. (ant must be installed of course - and the environment variables set). as ant is Java you can run it on any system: http://ant.apache.org/

Or you can use the collection() function, but I'm not sure if it works with all XSLT processors. See examples here: http://www.xmlplease.com/collection




回答2:


If you have access to a bash shell, you can do it this way: Navigate to the directory containing the files you want to process and type

for schemadoc in *.xsd
  do echo "$schemadoc ..."
  xsltproc myxslt.xsl $schemadoc > $schemadoc.output.txt
done

In doing so, change myxslt.xsl to the name of the stylesheet you are trying to run, and change the line beginning xsltproc to match the correct way to invoke your XSLT processor from the command line.

Or, if you have access to Oxygen, you can read up on how to apply a stylesheet to all the files (or all the *.xsd files) in a given directory, and do it that way.

Or, if you don't have access to either of these, find someone who works successfully and happily in the computing environment you find yourself in and ask them how THEY would do it.

Running a process over a collection of files is a basic skill and there are many, many ways to do it. It has nothing at all to do with the specific contents of your XSLT stylesheet and is not, fundamentally, an XSLT question unless for some reason it must be done within a single XSLT process (in which case, listen carefully to anything Dimitre Novatchev says). Find one, or three, or fifty-five, ways that work in your environment and learn them.



来源:https://stackoverflow.com/questions/12049913/xslt-loop-over-a-set-of-files-in-the-directory

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!