XSLT转换文件夹和多个子文件夹中的一组XML文件

时间:2013-12-09 17:10:00

标签: xml xslt ant xslt-2.0

我在一个文件夹和子文件夹中有一组xml文件,我需要通过将主题标题从UPPER CASE更改为Title Case来稍微修改。

更改后:我的出版物的第一段 应该是这样的:我的出版物的第一段

文件夹结构如下所示 文档/文件/文件夹1, 文档/文件/文件夹2, 文件/文件/文件夹3等..

我想将XSLT与Ant脚本或任何其他方法结合使用来执行更改。 覆盖源文件是可以的,因为我需要保持相同的文件夹结构。

这种方法XSLT: Transform XML files tree最接近我想要实现的目标,但我无法做到。

源XML文件如下所示:

<!DOCTYPE topic PUBLIC "-//OASIS//DTD DITA Topic//EN" "topic.dtd">
<topic xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" audience="(12-7-1)"
   id="parag128" ditaarch:DITAArchVersion="1.0"
   domains="(topic ui-d) (topic hi-d) (topic pr-d) (topic sw-d)                          (topic ut-d)"
   class="- topic/topic ">

   <title class="- topic/title ">FIRST PARAGRAPH OF MY PUBLICATION</title>

   <body class="- topic/body ">

      <p class="- topic/p ">The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.
         The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.
         The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.

      </p>

   </body>

</topic>

结果XML应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topic PUBLIC "-//OASIS//DTD DITA Topic//EN" "topic.dtd">
<topic xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" audience="(12-7-1)"
   id="parag128" ditaarch:DITAArchVersion="1.0"
   domains="(topic ui-d) (topic hi-d) (topic pr-d) (topic sw-d)                          (topic ut-d)"
   class="- topic/topic ">

   <title class="- topic/title ">First Paragraph Of My Publication</title>

   <body class="- topic/body ">

      <p class="- topic/p ">The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.
         The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.
         The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.

      </p>

   </body>

</topic>

我有这个XSLT     

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>
<xsl:param name="files" select="collection('../../*.dita;recurse=yes')"/>

<xsl:template match="topic/title/text()">
    <xsl:analyze-string select="." regex="\p{{L}}+">
        <xsl:matching-substring>
            <xsl:value-of select="concat(upper-case(substring(.,1,1)), lower-case(substring(.,2)))"/>
        </xsl:matching-substring>
        <xsl:non-matching-substring>
            <xsl:value-of select="."/>
        </xsl:non-matching-substring>
    </xsl:analyze-string>

</xsl:template>

来自这个问题Converting to text to lowercase in nodes and child nodes in xsl,但我无法让它适用于多个文件。

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

使用您的Ant xslt任务来驱动XSLT的应用程序,因此每个文件将运行一次Saxon。

拥有源和目标目录,因此您不会覆盖任何内容。在测试期间,您会很高兴。准备好上线后,添加一个额外步骤,将目标目录中的所有内容复制回源。额外的积分,只有在有变化时才能复制。

答案 1 :(得分:0)

您在xsl:collection()中使用的是xsl:parameter,但您从未使用该参数。

尝试对集合中的每个文档执行xsl:for-each,并使用xsl:result-document创建新文档。您可以使用document-uri获取文件的名称。

警告:当前示例将覆盖现有文件!要进行测试,请向href href="{document-uri(current())}.test"添加扩展名。)

此外,由于您使用的是Saxon-EE,请尝试使用saxon:discard-document()扩展功能。这将在处理后从Saxon的文档池中删除每个文档。这将使其可用于垃圾收集,因此您不会忘记内存。 (如果记忆是一个问题。)

示例(使用Saxon-EE 9.4测试):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/">
        <xsl:for-each select="collection('../../?recurse=yes;select=*.dita')/saxon:discard-document(.)" xmlns:saxon="http://saxon.sf.net/">
            <xsl:result-document href="{document-uri(current())}">
                <xsl:apply-templates/>
            </xsl:result-document>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="topic/title">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:analyze-string select="." regex="\p{{L}}+">
                <xsl:matching-substring>
                    <xsl:value-of select="concat(upper-case(substring(.,1,1)), lower-case(substring(.,2)))"/>
                </xsl:matching-substring>
                <xsl:non-matching-substring>
                    <xsl:copy-of select="."/>
                </xsl:non-matching-substring>
            </xsl:analyze-string>               
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

注意此样式表的输入将是任何XML文档。我在测试时使用样式表本身作为输入。


选择忽略parens中的文本。 (PUBLICATION HEADING (ABCD)变为Publication Heading (ABCD)

<xsl:analyze-string select="." regex="\p{{L}}+|\([^\(\)]+\)">
    <xsl:matching-substring>
        <xsl:choose>
            <xsl:when test="matches(.,'^\(')">
                <xsl:value-of select="."/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="concat(upper-case(substring(.,1,1)), lower-case(substring(.,2)))"/>                           
            </xsl:otherwise>
        </xsl:choose>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
        <xsl:copy-of select="."/>
    </xsl:non-matching-substring>
</xsl:analyze-string>

这可能不是最好/最可扩展的方式,但我只有几分钟。