【问题标题】:XSLT Input file with settings - change multiple output files带有设置的 XSLT 输入文件 - 更改多个输出文件
【发布时间】:2015-04-22 16:42:16
【问题描述】:

我正在使用 xslt 来编辑多个文件。我的输入文件是我的设置文件,它看起来像这样:

<root>
  <file>
    <folderin>/var/in/</folderin>
    <in>10</in>
    <folderout>/var/out</folderout>
    <out>20</out>
    <name>First file</name>
  </file>
</root>

示例文件:

<root>
  <element1 id1="10">
    ...
  </element1>
  <element2 id2="10" attribute="xyz">
    ...
  </element2>
</root>

还有我的 xslt 文件:

<?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes" encoding="utf-8"/>
        <xsl:template name="CopyXml" match="/*">
        <xsl:for-each select="file">
            <xsl:variable name="inputfile" select="concat(folderin, in, '.xml')"/>
            <xsl:variable name="outputfile" select="concat(folderout, out, '.xml')"/>

            <xsl:result-document method="xml" href="{$outputfile}">
                    <xsl:copy-of select="document($inputfile)/*"/>
            </xsl:result-document>
            </xsl:for-each>
        </xsl:template>

    </xsl:stylesheet>

在 /var/in/ 中有几百个文件,我只想编辑其中的几个(在本例中 /var/in/10.xml 带有退出文件 /var/out/20.xml)。在新文件中,我想将 id1 和 id2 属性值更改为我的“out”参数

我已经设法用我的 xslt 复制了那些具有适当名称的特定文件,但是我在应用任何模板时遇到问题,因此我可以更改这些文件。我尝试使用应用模板,但是我无法将这些模板应用到 $outputFile,它要么不做任何事情,要么将 $outputFile 与设置文件中的副本相附加;/ 有谁知道该怎么做?


编辑: 此示例文件的输出:

<root>
  <element1 id1="20">
    ...
  </element1>
  <element2 id2="20" attribute="xyz">
    ...
  </element2>
</root>

【问题讨论】:

  • 请编辑您的问题并显示您要为您显示的“示例文件”创建的结果。我也没有在您的代码中看到“out”参数,所以我不明白应该从哪里获取值。
  • 我已经添加了我想要的结果。现在“out”参数在:select="concat(folderout, out, '.xml')"。我尝试添加应用模板,其中没有参数,但它始终只应用于我的设置文件,而不是 $inputfile
  • 那么任何具有in 元素中值的属性都需要获取out 元素中给出的新值?属性名有什么限制吗?

标签: xml templates xslt copy


【解决方案1】:

目前你的样式表有:

        <xsl:result-document method="xml" href="{$outputfile}">
                <xsl:copy-of select="document($inputfile)/*"/>
        </xsl:result-document>

因此,您正在创建一个输出文件,其中将包含输入文件的副本

为了应用一些修改,你必须应用模板到输入文件,所以你需要:

        <xsl:result-document method="xml" href="{$outputfile}">
                <!-- further process the input file -->
                <xsl:apply-templates select="document($inputfile)/*"/>
        </xsl:result-document>

当然,您的样式表必须包含处理输入文件内容的模板,复制和修改相关部分。

您可以尝试增量方法来解决您的问题:

  • 首先,定义一个样式表,其中包含将单个输入文件转换为单个输出文件的规则
  • 一旦这些模板满足您的需要,请将它们复制到应用于设置文件的样式表中

这个样式表应该能满足你的需要:

XSLT 2.0:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes" encoding="utf-8"/>

    <!-- template to process the settings file -->
    <xsl:template match="/">
        <xsl:for-each select="root/file">
            <xsl:variable name="inputfile" select="concat(folderin, in, '.xml')"/>
            <xsl:variable name="outputfile" select="concat(folderout, out, '.xml')"/>

            <xsl:result-document method="xml" href="{$outputfile}">
                <xsl:apply-templates select="document($inputfile)/*" mode="processFiles">
                    <xsl:with-param name="outputValue" select="out" tunnel="yes"/>
                </xsl:apply-templates>
            </xsl:result-document>
        </xsl:for-each>
    </xsl:template>

    <!-- template to process the input files -->
    <!-- identity transformation -->
    <xsl:template match="* | @* | text()" mode="processFiles">
        <xsl:copy>
            <xsl:apply-templates select="* | @* | text()" mode="#current"/>
        </xsl:copy>
    </xsl:template>
    <!-- update parameters -->
    <xsl:template match="@id1 | @id2" mode="processFiles">
        <xsl:param name="outputValue" tunnel="yes"/>
        <xsl:attribute name="{name()}">
            <xsl:value-of select="$outputValue"/>
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

值得注意的点:

  • 您不能只复制输入文件,您必须对其应用模板才能更改其中的某些部分
  • 将模板应用到外部文件时,会传递一个名为outputValue 的参数;使用tunnel parameter 可以避免每次调用xsl:apply-templates 时显式传递它的麻烦
  • 我使用带有mode="processFile"的模板来处理外部文件的内容;在这种简单的情况下并不是绝对必要的,但是在使用较大的样式表时,这是一个小“技巧”​​,有助于避免 settings 文件 的模板与 外部文件的模板之间的优先级冲突
    • 身份模板只复制元素、属性和文本节点
    • 属性id1id2 的特定模板使用隧道参数将现有值替换为所需值

【讨论】:

  • ”是什么意思?在我的情况下,除了对这些属性的更改之外,我想要几乎相同的文件,并且据我所知,它可能应该是“应用模板”。我认为您是对的,我没有尝试增量方法,并且我的转换模板中可能存在一些基本错误。明天早上我会尝试做下一件事:)
  • 抱歉不清楚,这只是一个注释,强调我所做的更改以及原因。
  • 好的,我还是有问题。当我启动它指向我要更改的文件时,一切正常 - 我使用 。但是我不知道如何将模板应用于“document($inputfile)”——即使用 这样的东西。你知道怎么做吗?
  • @Pumar 我编辑了答案,添加了一个完整的样式表,可以满足您的需要,并附上一些解释。
  • 正是我需要的,谢谢你的帮助:) 我觉得 xslt 是一种非常强大的语言,但是缺乏使用更高级元素如 {name()}、text( ) 或 #current.
猜你喜欢
  • 2021-04-20
  • 2010-11-10
  • 1970-01-01
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
相关资源
最近更新 更多