如何基于另一个XML文件添加或修改节点?

时间:2015-10-02 15:06:48

标签: xml xslt

我有两个文件(File1):

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

和(File2):

<studentstoamend>
    <STUDENT><OWNINST>123456|5</OWNINST><MODE>01</MODE></STUDENT>
    <STUDENT><OWNINST>111112|1</OWNINST><MODE>31</MODE></STUDENT>
</studentstoamend>

对于File2中的OWNINST,我需要更新File1中的模式。如果File1中没有模式,那么我需要在ELQ节点之后添加一个模式。

我确信在XML样式表中这并不难,但似乎无法做到。

编辑05/10/2015 11:03

所以,感谢@bknights我,XSLT现在将MODE丢失,这很好。我已设法调整文件进行解析。下一个问题是它删除了实例标签,所以一切都向上移动到学生级别。我试过摆弄它,但不能不这样做。有人可以帮忙吗?这是我现在的代码:

<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:key name="studentRefs" match="STUDENT" use="OWNINST"/>
<xsl:variable name="studentRefs" select="document('MCDATE - students to amend.xml')"/>

<xsl:template match="Instance">
    <xsl:apply-templates select="*">
        <xsl:with-param name="id" select="OWNINST"/>
    </xsl:apply-templates>
    <xsl:if test="count(MCDATE)= 0">
        <xsl:call-template name="checkMcdate">
            <xsl:with-param name="id" select="OWNINST"/>
        </xsl:call-template>
     </xsl:if> 
</xsl:template> 

        <xsl:template match="MCDATE">
            <xsl:param name="id"/>
            <xsl:call-template name="checkMcdate">
                <xsl:with-param name="id" select="$id"/>
                <xsl:with-param name="default" select="."/>
            </xsl:call-template>
         </xsl:template>

            <xsl:template name="checkMcdate">
                <xsl:param name="id"/>
                <xsl:param name="default" select="''"/>
                <xsl:for-each select="$studentRefs/studentstoamend">
                    <xsl:choose>
                        <xsl:when test="count(key('studentRefs', $id)) = 1">
                            <xsl:copy-of select="key('studentRefs', $id)/MCDATE"/>
                        </xsl:when>
                        <xsl:when test="not($default='')">
                            <MCDATE><xsl:value-of select="$default"/></MCDATE>
                        </xsl:when>
                    </xsl:choose>
                </xsl:for-each>
            </xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

这应该让你开始。没有解析。它至少会为你提供一些概念来查找。

<xsl:key name="studentRefs" match="STUDENT" use="OWNINST"/>
<xsl:variable name="studentRefs" select="document('studentRefs.xml')"/>

<xsl:template match="instance">
   <xsl:apply-templates select="*">
      <xsl:with-param name="id" select="OWNINST"/>
   </xsl:apply-templates>
   <xsl:if test="count(MODE)= 0">
   <xsl:call-template name="checkMode">
      <xsl:with-param name="id" select="OWNINST"/>
   </xsl:call-template>
...

<xsl:template match="MODE">
   <xsl:param name="id"/>
   <xsl:call-template name="checkMode">
      <xsl:with-param name="id" select="$id"/>
      <xsl:with-param name="default" select="."/>
   </xsl:call-template>

<xsl:template name="checkMode">
  <xsl:param name="id"/>
  <xsl:param name="default" select="''"/>
  <xsl:for-each select="$studentRefs/studentstoamend">
    <xsl:choose>
     <xsl:when test="count(key('studentRefs', $id)) = 1)>
        <xsl:copy-of select="key('studentRefs', $id)/MODE"/>
     </xsl:when>
     <xsl:when test="not($default='')">
      <MODE><xsl:value-of select="$default"/></MODE>
     </xsl:when>
    </xsl:choose>
  </xsl:for-each>
 </xsl:template>