应用XSLT时重复节点

时间:2016-12-06 11:30:44

标签: xml xslt

我尝试使用XSLT 1.0转换节点,将其转换为新节点,然后使用其中一个属性作为其值,但它正在创建多个节点而不是覆盖一个并创建一个额外的节点,我该如何解决这个问题?

以下是数据的示例部分,其中我感兴趣的节点是' unitid'。应将此节点的值复制到新节点,< physloc'和' unitid'价值已更改为' id'属性。

现有输入:

<c03 level="subseries">
              <did>
                 <unitid encodinganalog="isadg311" id="cnda.94.02.02">D1148/2/2</unitid>
                 <unittitle encodinganalog="isadg312 marc245">Bundle</unittitle>
                 <unitdate encodinganalog="isadg313 marc260" normal="19350701/19750108">1 Jul 1935-8 Jan 1975; n.d.</unitdate>
                 <physdesc encodinganalog="isadg315 marc300">
                    <extent>1 bundle; 11 items.</extent>
                    <genreform />
                    <physfacet />
                 </physdesc>
              </did>

期望的结果:

<c03 level="subseries">
          <did>
             <unitid encodinganalog="isadg311">cnda.94.02.02</unitid>
             <unittitle encodinganalog="isadg312 marc245">Bundle</unittitle>
             <unitdate encodinganalog="isadg313 marc260" normal="19350701/19750108">1 Jul 1935-8 Jan 1975; n.d.</unitdate>
             <physdesc encodinganalog="isadg315 marc300">
                <extent>1 bundle; 11 items.</extent>
                <genreform />
                <physfacet />
             </physdesc>
             <physloc>D1148/2/2</physloc>
          </did>

一些一般性问题,并非所有&#39; unitid&#39;节点有一个&#39; id&#39;属性以及这种情况下的&#39; unitid&#39;价值应该保留。此外,还有一些记录显示这个&#39; id&#39;属性在&#39;做过&#39;节点,例如

<did id="uni.07.01.06.14">
  <unitid encodinganalog="isadg311">P4A/5/9</unitid>

在这种情况下,&#39; id&#39;属性来自&#39;做过&#39;节点应该成为&lt; unitid&#39;具有&#39; unitid&#39;的值被设定为&#39; physloc&#39; e.g。

<did>
  <unitid encodinganalog="isadg311">uni.07.01.06.14</unitid>
  <physloc>P4A/5/9</physloc>

我目前的样式表是这样的:

<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:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes"/>
<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
</xsl:template>
<xsl:template match="did">
    <xsl:param name="physid" select="unitid"/>
    <xsl:param name="eadid">
        <xsl:choose>
            <xsl:when test="@id">
                <xsl:value-of select="@id" />
            </xsl:when>
            <xsl:when test="unitid/@id">
                <xsl:value-of select="unitid/@id"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="unitid"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:param>
    <xsl:copy>
        <xsl:copy-of select="*" />
        <physloc><xsl:value-of select="$physid" /></physloc>
        <unitid><xsl:value-of select="$eadid" /></unitid>
    </xsl:copy>
</xsl:template>

对于没有&#39; id&#39; &lt; unitid&#39;中的属性结果是:

<did>
  <repository encodinganalog="marc852">
    <corpname>
           University of Liverpool,
           <subarea>Special Collections and Archives</subarea>      </corpname>
  </repository>
  <unitid countrycode="GB" repositorycode="141" encodinganalog="isadg311">CNDA</unitid>
  <physloc>CNDA</physloc>
  <unitid>CNDA</unitid>
  <physloc>CNDA</physloc>
  <unitid>CNDA</unitid>

哪里有“id”&#39;在&lt; unitid&#39;:

<did>
          <unitid encodinganalog="isadg311" id="cnda.94.01.17">D1148/1/17</unitid>
          <unittitle encodinganalog="isadg312 marc245">Poem</unittitle>
          <unitdate encodinganalog="isadg313 marc260" normal="19000101/19591231">n.d.</unitdate>
          <physdesc encodinganalog="isadg315 marc300">
            <extent>1 item; 2 pieces.</extent>
            <genreform/>
            <physfacet/>
          </physdesc>
          <physloc>D1148/1/17</physloc>
          <unitid>cnda.94.01.17</unitid>
          <physloc>D1148/1/17</physloc>
          <unitid>cnda.94.01.17</unitid>
        </did>

那里有一个&#39; id&#39;在&#39;做过&#39;节点:

 <did>
          <unitid encodinganalog="isadg311">D1148/2/2</unitid>
          <unittitle encodinganalog="isadg312 marc245">Bundle</unittitle>
          <unitdate encodinganalog="isadg313 marc260" normal="19350701/19750108">1 Jul 1935-8 Jan 1975; n.d.</unitdate>
          <physdesc encodinganalog="isadg315 marc300">
            <extent>1 bundle; 11 items.</extent>
            <genreform/>
            <physfacet/>
          </physdesc>
          <physloc>D1148/2/2</physloc>
          <unitid>cnda.94.02.02</unitid>
          <physloc>D1148/2/2</physloc>
          <unitid>D1148/2/2</unitid>
        </did>

如何更改样式表以便我只获得一个&#39; unitid&#39;和&#39; physloc&#39;有正确的价值?我正在使用的XML文件是嵌套的,并且&#39; unitid&#39;节点可以出现在多个级别。

2 个答案:

答案 0 :(得分:1)

再看一下我的样式表,看起来它是模板中的<xsl:copy>语句。删除它已经成功了。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes"/>
    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="did">
        <xsl:param name="physid" select="unitid"/>
        <xsl:param name="eadid">
            <xsl:choose>
                <xsl:when test="@id">
                    <xsl:value-of select="@id" />
                </xsl:when>
                <xsl:when test="unitid/@id">
                    <xsl:value-of select="unitid/@id"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="unitid"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:param>
        <xsl:copy-of select="*" />
        <physloc><xsl:value-of select="$physid" /></physloc>
        <unitid><xsl:value-of select="$eadid" /></unitid>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

你的转变分解为这些基本规则:

  1. 除了
  2. 之外,应该按原样复制所有内容
  3. 应删除unitid/@id属性
  4. 新的unitid文字值应取自@id属性
  5. 应创建新的physloc元素,并接收旧的unitid文字值
  6. 这些规则中的每一个都可以转换为一个单独的模板来实现它。

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <!-- 1. identity template copies everything as is -->
        <xsl:template match="node() | @*">
            <xsl:copy>
                <xsl:apply-templates select="node() | @*" />
            </xsl:copy>
        </xsl:template>
    
        <!-- 2. if there is an id attribute, delete it -->
        <xsl:template match="unitid/@id" />
    
        <!-- 3. move the value of the id attribute into the element value -->
        <xsl:template match="unitid[@id]/text()">
            <xsl:value-of select="../@id" />
        </xsl:template>
    
        <!-- 4. create a <physloc> element inside <did> -->
        <xsl:template match="did[not(physloc)]">
            <xsl:copy>
                <xsl:apply-templates select="node() | @*" />
                <physloc><xsl:value-of select="unitid" /></physloc>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

    使用此样式表,您的输入将转换为所需的输出:

    <c03 level="subseries">
       <did>
          <unitid encodinganalog="isadg311">cnda.94.02.02</unitid>
          <unittitle encodinganalog="isadg312 marc245">Bundle</unittitle>
          <unitdate encodinganalog="isadg313 marc260" normal="19350701/19750108">1 Jul 1935-8 Jan 1975; n.d.</unitdate>
          <physdesc encodinganalog="isadg315 marc300">
             <extent>1 bundle; 11 items.</extent>
             <genreform/>
             <physfacet/>
          </physdesc>
          <physloc>D1148/2/2</physloc>
       </did>
    </c03>
    

    请注意,teplates 2和3仅与具有@id属性的特定情况相匹配。如果没有,则<unitid>元素只是按原样复制。换句话说,如果输入已经是所需的格式,则不会发生任何事情。