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

Change multiple values in an XML file to those referenced in another XML file

我有一个很大的 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 等等

非常感谢


编辑:22/9/2015

感谢亚伯的帮助。貌似只是复制原文件,没有做任何修改

如果我可以按如下方式构建 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:45pm 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>

非常感谢

<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

Would it help if I could structure file2.xml as follows?

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