XSL - 使用带有多个源XML文件的调用模板

时间:2015-06-12 10:30:12

标签: xml xslt

我有一个XSL文件,用于从多个源转换/构建XML文件,其中需要动态更新多个元素和属性。我想知道这种情况是否应该在带有参数的<call-template/>块中起作用。

当我将外部文件引用作为参数传递时,&#34;代码&#34; EXPORT/Top/Shapes/Shape/Material下的属性未更新:

<xsl:template match="Shapes">
    <xsl:copy>
        <xsl:for-each select="document('..\TempReportData\TextXML_Output.xml')/Job/Benchtops/Benchtop">
            <xsl:apply-templates select="document('..\DesignMaster\EmptyShapeElement.xml')" />
            <xsl:call-template name="updateMaterial">
                <xsl:with-param name="mCode" select="./Top_number"/>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

<xsl:template name="updateMaterial" match="@Code[parent::Material]">
<xsl:param name="mCode"/>
<xsl:attribute name="Code">
    <xsl:value-of select="$mCode">
</xsl:attribute>
</xsl:template>

这是期望的结果,<Material></Material>元素中的Code属性从外部文件更新:

<?xml version="1.0"?>
<EXPORT>
<Top Id="1" Code="B90512">
<Shapes>
<!--Shape-->
<Shape Id="1" Code="Penisola">
<!--Material-->
<Material Code="TOP(2257)"></Material>
</Shape>
<!--Shape-->
<Shape Id="1" Code="Penisola">
<!--Material-->
<Material Code="TOP(2260)"></Material>
</Shape>
</Shapes>
</Top>
</EXPORT>

XML文件TextXML_Output.xml是:

<?xml version="1.0"?>
<Job>
<Job_Number>B90512</Job_Number>
<Job_Address>2nd Floor/ 28-32 Albert Road   VIC 3205</Job_Address>
<Benchtops>
<Benchtop>
<Top_number>TOP(2257)</Top_number>
</Benchtop>
<Benchtop>
<Top_number>TOP(2260)</Top_number>
</Benchtop>
</Benchtops>
</Job>

在使用多个模板和文件时,我有点迷失,但在我看来,这应该可行,但它没有。

1 个答案:

答案 0 :(得分:1)

您的Shapes匹配模板

存在问题
<xsl:template match="Shapes">
    <xsl:copy>
        <xsl:for-each select="document('..\TempReportData\TextXML_Output.xml')/Job/Benchtops/Benchtop">
            <xsl:apply-templates select="document('..\DesignMaster\EmptyShapeElement.xml')" />
            <xsl:call-template name="updateMaterial">
                <xsl:with-param name="mCode" select="./Top_number"/>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

首先在输出中创建一个Shapes元素。然后迭代另一个文档中的所有Benchtop元素,并为每个元素复制一个“Empty Shape Xml”作为您创建的Shapes元素的子元素。但是,您调用updateMaterial模板,该模板添加了一个属性。这实际上会尝试在您之前创建的父Shapes元素上创建一个属性,但是根据W3C Specification ...

  

在添加子项后向元素添加属性   它;实现可以发出错误信号或忽略错误   属性。

因此,在您的情况下,看起来XSLT处理器忽略了属性,而不是抛出错误。

但是从查看您要实现的内容来看,您似乎希望将该属性添加到Material元素中,该元素是您正在复制的“EmptyShapeElement.xml”的一部分。

您可以做的是更改您的身份模板,我认为您的完整XSLT正在使用该模板来携带mCode参数....

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

然后在选择“EmptyShapeElement.xml”时将Top_Number值作为此参数传递

<xsl:apply-templates select="$EmptyShapeElement">
  <xsl:with-param name="mCode" select="Top_number" />
</xsl:apply-templates>

最后,您现有的属性模板不需要立即命名

<xsl:template match="Material/@Code">
    <xsl:param name="mCode"/>
    <xsl:attribute name="Code">
        <xsl:value-of select="$mCode" />
    </xsl:attribute>
</xsl:template>

(这是假设您要替换的“EmptyShapeElement.xml Material Code”属性中的does indeed have an existing元素。

试试这个XSLT

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

    <xsl:variable name="TextXML_Output" select="document('..\TempReportData\TextXML_Output.xml')" />
    <xsl:variable name="EmptyShapeElement" select="document('..\DesignMaster\EmptyShapeElement.xml')" />

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

    <xsl:template match="Shapes">
        <xsl:copy>
            <xsl:for-each select="$TextXML_Output/Job/Benchtops/Benchtop">
                <xsl:apply-templates select="$EmptyShapeElement">
                  <xsl:with-param name="mCode" select="Top_number" />
                </xsl:apply-templates>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Material/@Code">
        <xsl:param name="mCode"/>
        <xsl:attribute name="Code">
            <xsl:value-of select="$mCode" />
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>