将XML文件中的多个值更改为另一个XML文件中引用的值

时间:2015-09-21 15:44:24

标签: xml xslt xslt-1.0

我有一个大型XML文件,我需要更改其中ID号(OWNINST)与另一个XML文件中的ID匹配的某些值。

我的大型XML文件'file1.xml'采用以下格式:

    <institution>
    <ukprn>1234</ukprn>
    <course>
        <courseID>1</courseID>
        <courseaim>X99</courseaim>
    </course>
    <student>
        <birthdate>30/10/1985</birthdate>
        <instance>
            <OWNINST>123456|5</OWNINST>
            <FC>1</FC>
            <STULOAD>100</STULOAD>
            <elq>4</elq>
            <MODE>31</MODE>
        </instance>
    </student>
    <student>
        <birthdate>01/02/1999</birthdate>
        <instance>
            <OWNINST>654321|1</OWNINST>
            <FC>2</FC>
            <elq>2</elq>
        </instance>
        <instance>
            <OWNINST>654321|2</OWNINST>
            <FC>6</FC>
            <elq>1</elq>
        </instance>
    </student>
</institution>

有多个学生,每个学生可以有多个实例。

我有另一个xml文件'File2.xml',其结构如下:

<studentstoamend>
<OWNINST>123456|5</OWNINST><MODE>01</MODE><STULOAD>100</STULOAD>
<OWNINST>111112|1</OWNINST><MODE>31</MODE><STULOAD>75</STULOAD>
</studentstoamend>

对于File2.xml中的每个学生,我想将File1.xml中的字段值更改为File2.xml中列出的值。不应更改未列在File2.xml中的任何学生。

请帮助我,因为我似乎无法做到这一点。

这是我走了多远:

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

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

<xsl:template match="Student/Instance[OWNINST = document('File2.xml')/studentstoamend/OWNINST]/MODE">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>        
    </xsl:copy>
</xsl:template>

或者,我可以运行多个样式表,一次将数据放在一个节点中,即在一个样式表中更新MODE,在另一个样式表中更新MCDATE等等

非常感谢

编辑:2015年9月22日

感谢您的帮助Abel。它似乎只是复制原始文件,但没有做出修改。

如果我可以按如下方式构建file2.xml会有帮助吗?

<?xml version="1.0" encoding="UTF-8"?>
<studentstoamend>
    <student><OWNINST>328352|2</OWNINST><MODE>31</MODE><STULOAD>50</STULOAD><MCDATE>12/01/2015</MCDATE></student>
    <student><OWNINST>652508|3</OWNINST><MODE>01</MODE><STULOAD>100</STULOAD><MCDATE>15/11/2014</MCDATE></student>
</studentstoamend>

这是我现在拥有的代码

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

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

<xsl:variable name="students2" select="document('File2.xml')/studentstoamend" />

<xsl:template match="student/instance[OWNINST = document('File2.xml')/studentstoamend/OWNINST]/MODE">
    <xsl:variable name="owninst" select="OWNINST" />
    <xsl:apply-templates select="$students2[OWNINST = $owninst]/*" mode="file2" />
</xsl:template>

<!-- adjust this, or add more templates in this mode if changes in element names/values are needed -->
<xsl:template match="node() | @*" mode="file2">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" mode="file2" />
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

我会将最后一部分代码的哪一部分更改为定位特定节点,例如模式?

由于

编辑1:24 pm 22/09/15

我希望看到的输出是:

    <institution>
    <ukprn>1234</ukprn>
    <course>
        <courseID>1</courseID>
        <courseaim>X99</courseaim>
    </course>
    <student>
        <birthdate>30/10/1985</birthdate>
        <instance>
            <OWNINST>123456|5</OWNINST>
            <FC>1</FC>
            <STULOAD>100</STULOAD> <!--Updated to 100 (although in this case it already was 100 so no change) -->
            <elq>4</elq>
            <MODE>01</MODE> <!--Updated to 01 -->
        </instance>
    </student>
    <student>
        <birthdate>01/02/1999</birthdate>
        <instance>
            <OWNINST>654321|1</OWNINST>
            <FC>2</FC>
            <elq>2</elq>
        </instance>
        <instance>
            <OWNINST>654321|2</OWNINST>
            <FC>6</FC>
            <elq>1</elq>
        </instance>
    </student>
</institution>

非常感谢

2 个答案:

答案 0 :(得分:0)

<xsl:template match="Student/Instance[OWNINST = document('File2.xml')/studentstoamend/OWNINST]/MODE">

这不符合任何内容,您的输入文件有studentinstance作为元素名称,XML区分大小写。

在此模板中,您可以在原始文档(File1.xml)上应用模板。要采用File2.xml中的更改,您必须将模板应用于第二个文档,其中包括:

<xsl:variable name="students2" select="document('File2.xml')/studentstoamend" />

<xsl:template match="student/instance[OWNINST = document('File2.xml')/studentstoamend/OWNINST]">
    <xsl:variable name="owninst" select="OWNINST" />
    <xsl:copy>
        <xsl:apply-templates select="$students2[OWNINST = $owninst]/*" mode="file2" />
    </xsl:copy>
</xsl:template>

<!-- adjust this, or add more templates in this mode if changes in element names/values are needed -->
<xsl:template match="node() | @*" mode="file2">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" mode="file2" />
    </xsl:copy>
</xsl:template>

更新:将主模板的焦点从MODE更改为OWNINST

答案 1 :(得分:0)

  

如果我可以按如下方式构建file2.xml会有帮助吗?

<?xml version="1.0" encoding="UTF-8"?>
<studentstoamend>
    <student><OWNINST>328352|2</OWNINST><MODE>31</MODE><STULOAD>50</STULOAD><MCDATE>12/01/2015</MCDATE></student>
    <student><OWNINST>652508|3</OWNINST><MODE>01</MODE><STULOAD>100</STULOAD><MCDATE>15/11/2014</MCDATE></student>
</studentstoamend>

是的,那样会更方便。试试这种方式:

XSLT 1.0

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

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

<xsl:template match="instance">
    <xsl:variable name="amend" select="document('File2.xml')/studentstoamend/student[OWNINST=current()/OWNINST]"/>
    <xsl:copy>
        <xsl:choose>
            <xsl:when test="$amend">
                <xsl:apply-templates select="@*|node()[not(self::MODE or self::STULOAD)]"/>
                <xsl:apply-templates select="$amend/MODE | $amend/STULOAD"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>