如何根据多个条件在特定点将一个XML文件中的记录插入另一个XML文件?

时间:2015-09-07 09:58:14

标签: xml xslt

我想要合并两个xml文件。我正在使用OXYGEN软件通过XML Sytlesheets来做到这一点。文件2向文件1添加了更多细节,为每个需要一个的学生添加了一个条目档案。我当前的xsl代码(下面)似乎有效,但它在Student节点的底部添加了条目配置文件,而我想在<YRPRG>之后添加它。这些文件在<PIDM><NUMHUS>上都匹配。我不认为这太难了,但我不熟悉XML,似乎无法使其发挥作用。有人可以帮忙解决这个问题吗?

文件1(XML):

<institution>
    <student>
        <PIDM>1</PIDM>
        <NUMHUS>12</NUMHUS>
        <YRPRG>1</YRPRG>
        <Something>
            <term>7</term>
            <shortDescription>8</shortDescription>
        </Something>
    </student>

    <student>
        <PIDM>2</PIDM>
        <NUMHUS>1</NUMHUS>
        <YRPRG>2</YRPRG>
        <something>
            <term>70</term>
            <shortDescription>80</shortDescription>
        </something>
    </student>

    <student>
        <PIDM>34</PIDM>
        <NUMHUS>1</NUMHUS>
        <YRPRG>1</YRPRG>
        <Something>
            <term>5</term>
            <shortDescription>7</shortDescription>
        </Something>
    </student>
</institution>

文件2(XML):

<studentstoadd>
    <entryprofile>
        <PIDM>1</PIDM>
        <NUMHUS>12</NUMHUS>
        <PREVINST>1U40608</PREVINST>
        <QUALENT3>1HUK</QUALENT3>
        <WELBACC>1</WELBACC>
    </entryprofile>

    <entryprofile>
        <PIDM>2</PIDM>
        <NUMHUS>1</NUMHUS>
        <PREVINST>2U40608</PREVINST>
        <QUALENT3>2HUK</QUALENT3>
        <WELBACC>2</WELBACC>
    </entryprofile>

    <entryprofile>
        <PIDM>2</PIDM>
        <NUMHUS>2</NUMHUS>
        <DOMICILE>XK</DOMICILE>
        <QUALENT3>3HUK</QUALENT3>
        <WELBACC>3</WELBACC>
    </entryprofile>
</studentstoadd>

所需的输出(XML):

<institution>
    <student>
        <PIDM>1</PIDM>
        <NUMHUS>12</NUMHUS>
        <YRPRG>1</YRPRG>
        <entryprofile>
            <PREVINST>1U40608</PREVINST>
            <QUALENT3>1HUK</QUALENT3>
            <WELBACC>1</WELBACC>
        </entryprofile>
        <Something>
            <term>7</term>
            <shortDescription>8</shortDescription>
        </Something>
    </student>

    <student>
        <PIDM>2</PIDM>
        <NUMHUS>1</NUMHUS>
        <YRPRG>2</YRPRG>
        <entryprofile>
            <PREVINST>2U40608</PREVINST>
            <QUALENT3>2HUK</QUALENT3>
            <WELBACC>2</WELBACC>
        </entryprofile>
        <something>
            <term>70</term>
            <shortDescription>80</shortDescription>
        </something>
    </student>
</institution>

我的样式表包含以下代码:

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

<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

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


<xsl:template match="student">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:copy-of select="document('s2.xml')//entryprofile[PIDM=current()/PIDM]"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="student">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:copy-of select="document('s2.xml')//entryprofile[NUMHUS=current()/NUMHUS]"/>
    </xsl:copy>
</xsl:template>

2 个答案:

答案 0 :(得分:1)

如果要在YRPRG之后插入节点,则应在匹配YRPRG的模板中执行此操作 - 例如:

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="YRPRG">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
    <xsl:copy-of select="document('s2.xml')//entryprofile[PIDM=current()/../PIDM and NUMHUS=current()/../NUMHUS]"/>
</xsl:template>

</xsl:stylesheet>

注意:最好使用 key 查找其他文档中的匹配条目。确切的方法取决于您使用的是XSLT 1.0还是2.0(您没有回答我关于您的版本的问题)。

答案 1 :(得分:0)

  

我当前的xsl代码(如下所示)似乎有效但是它在学生节点的底部添加了条目配置文件,而我想在

之后添加它

改变这个:

<xsl:template match="student">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:copy-of select="document('s2.xml')//entryprofile[PIDM=current()/PIDM]"/>
    </xsl:copy>
</xsl:template>

对此:

<xsl:template match="student">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
    <xsl:copy-of select="document('s2.xml')//entryprofile[PIDM=current()/PIDM]"/>
</xsl:template>

会在 student元素后添加,正如您在问题中提到的那样。这是有效的,因为xsl:copy创建了一个浅的副本(即,只复制student元素,但不复制其子元素)。以下xsl:apply-templates应用其子项的模板(处理节点)。通过在xsl:copy-of内添加xsl:copy ,您可以将其作为student子项的一部分。通过将放在 xsl:copy之后,将其设为兄弟节点。

(编辑)或更改为此,如果您的引用要求将其作为student的第一个孩子:

<xsl:template match="student">
    <xsl:copy>
        <xsl:copy-of select="document('s2.xml')//entryprofile[PIDM=current()/PIDM]"/>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

注1:使用xsl:copy-of,无法进一步处理您从s2.xml文档中选择的节点(如果需要)。如果要修改其内容,可以将模板应用于它们。为防止将匹配模板与原始源文档混合,您可以使用模式。

注2:你有两个<xsl:template match="student">,其中任何一个都没有xsl:next-match,所以只有最后一个匹配(XSLT 2.0通常的行为,但可能依赖于在处理器上,XSLT 3.0依赖于xsl:mode声明。如果您要为每个entryprofile附加两个student,请按以下方式添加:

<xsl:template match="student">
    <xsl:variable name="entryprofiles" select="document('s2.xml')//entryprofile" />
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
    <xsl:copy-of select="$entryprofiles[PIDM=current()/PIDM]"/>
    <xsl:copy-of select="$entryprofiles[NUMHUS=current()/NUMHUS]"/>
</xsl:template>

注3:在你写的评论中写道:

  

文件在PIDM和NUMHUS上匹配,我想在YRPRG之后插入相关学生的参赛资料。

但我不知道&#34;相关学生&#34;手段。这似乎与您原始问题的问题不同,在这种情况下,我建议您提出一个新问题,指明您在哪里遇到麻烦。

大编辑(基于评论)

来自你的评论:

  

谢谢亚伯。相关学生我只是意味着文件1中的PIDM和NUMHUS与文件2中的PIDM和NUMHUS组合相匹配的学生

显然,michael.hor257k在他的OP上发表了评论。你应该用钥匙解决这个问题。但是,由于我认为这是一个高级主题而你说你刚刚开始,所以没有键就可以做到这一点(一旦你开始学习键,你可以问一个不同的问题)。

<!-- globabl variable, remove local one -->
<xsl:variable name="entryprofiles" select="doc('s2.xml')/*/entryprofile" />

<!-- change your copy-of as follows -->
<xsl:copy-of select="$entryprofiles[PIDM=current()/PIDM][NUMHUS=current()/NUMHUS]"/>