Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 带设置的XSLT输入文件-更改多个输出文件_Xml_Templates_Xslt_Copy - Fatal编程技术网

Xml 带设置的XSLT输入文件-更改多个输出文件

Xml 带设置的XSLT输入文件-更改多个输出文件,xml,templates,xslt,copy,Xml,Templates,Xslt,Copy,我正在使用xslt编辑多个文件。我有一个输入文件,它是我的设置文件,如下所示: <root> <file> <folderin>/var/in/</folderin> <in>10</in> <folderout>/var/out</folderout> <out>20</out> <name>First file<

我正在使用xslt编辑多个文件。我有一个输入文件,它是我的设置文件,如下所示:

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

/var/in/
10
/var/out
20
第一档
示例文件:

<root>
  <element1 id1="10">
    ...
  </element1>
  <element2 id2="10" attribute="xyz">
    ...
  </element2>
</root>
<root>
  <element1 id1="20">
    ...
  </element1>
  <element2 id2="20" 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和exit file/var/out/20.xml)。在新文件中,我想将id1和id2属性值更改为我的“out”参数

我已经用xslt成功地复制了那些具有足够名称的特定文件,但是我在应用任何模板以便更改这些文件时遇到了问题。我已尝试使用应用模板,但我无法将这些模板应用到$outputFile,它可能没有执行任何操作,或者将$outputFile与“从设置文件复制”一起追加;/有人知道怎么做吗


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

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

...
...

此时您的样式表有:

        <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>

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

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

  • 首先,使用规则定义样式表,将单个输入文件转换为单个输出文件
  • 一旦这些模板完成了您需要的操作,就将它们复制到应用于设置文件的样式表中

此样式表应满足您的需要:

XSLT2.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
    的参数;每次调用
    xsl:apply-templates
  • 我使用带有
    mode=“processFile”
    的模板来处理外部文件的内容;在这种简单的情况下,这不是绝对必要的,但在使用较大的样式表时,这是一个小“技巧”,有助于避免设置文件模板和外部文件模板之间的优先级冲突
    • 标识模板仅复制元素、属性和文本节点
    • 属性
      id1
      id2
      的特定模板使用隧道参数将现有值替换为所需值

请编辑您的问题,并显示您要为显示的“示例文件”创建的结果。我在代码中也没有看到“out”参数,所以我不知道该值应该从何处获取。我已经添加了我想要的结果。目前,“out”参数位于:select=“concat(folderout,out,'.xml')”。我已尝试添加应用模板,其中有out参数,但它始终仅应用于我的设置文件,而不是$InputFiles。因此,在
in
元素中具有值的任何属性都需要在
out
元素中获得给定的新值?属性名是否有任何限制?您所说的“”是什么意思?在我的例子中,除了对那些属性的更改之外,我想要几乎相同的文件,正如我所了解的,可能应该是通过“应用模板”。我认为你们是对的,我并没有尝试增量方法,也许在我的转换模板中有一些基本的错误。明天早上我会试着做下一件事:)对不起,我不清楚,这只是一个评论,强调我所做的改变,以及为什么。好的,所以我仍然有一个问题。当我指向我想要更改的文件时,一切都正常工作——我使用。但是,我不知道如何将模板应用于“document($inputfile)”——即使用@Pumar编辑答案,添加一个完整的样式表,该样式表应该满足您的需要,并提供一些解释。这正是我所需要的,感谢您的帮助:)我觉得xslt是一种非常强大的语言,但是缺少使用{name()}、text()或#current等更高级元素的好教程。