2016-12-06 49 views
0

我試圖使用XSLT 1.0來轉換節點並將其複製到一個新節點,然後使用它的一個屬性作爲其值,但它創建了多個節點重寫一個並創建一個額外的,我該如何解決這個問題?當應用XSLT時重複節點

下面是我感興趣的節點是'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> 

一些一般性的問題,並非所有的「單元ID」節點有一個「id」屬性並在這樣的情況下,' unitid'值應該被保留。此外,還有一些記錄,其中這個「id」屬性是在「做」節點,例如

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

在這種情況下從「做」節點的「id」屬性應成爲價值「的UnitID」 'unitid'的值被設置爲'physloc',例如

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

對於那裏是在 '單元ID' 結果沒有 '身份證' 屬性記錄是這樣的:

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

'unitid'中有'id':

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

,並在「做」節點,那裏有一個「身份證」:

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

如何改變我的樣式,這樣我只得到一個「單元ID」和「physloc」正確的值?我正在使用的XML文件是嵌套的,'unitid'節點可以出現在多個層次上。

+0

爲什麼downvote而不解釋爲什麼?不是很有幫助。 – joesch

+1

我只能猜測這是因爲問題是以一種相當混亂的方式寫的。技術上所有東西都在那裏(輸入,期望輸出,當前嘗試,問題描述),但主觀上這個問題有點壓倒性。 – Tomalak

+0

公平點 - 我會盡量更具描述性而不會失去技術上的必需品。 – joesch

回答

1

您的轉換分解爲這些基本規則:

  1. 一切都應該是原樣複製,除了
  2. unitid/@id屬性應該被刪除
  3. unitid文本值應取來自@id屬性
  4. 應創建一個新的physloc元素並接收舊的unitid文本值

這些規則中的每一個都可以轉換爲一個單獨的模板來執行。

<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>元素只是原樣複製。換句話說,如果輸入已經是所需的格式,則什麼都不會發生。

+0

謝謝,這很有道理 - 只需加上以下內容,如果有 @id,則會去 joesch

+0

儘管與規則#3衝突,除非這兩個條件永遠不會發生在同時。 – Tomalak

+0

*應該*只有一個。但是, @id中的值不應該存在。(我真的討厭數據清理)。 – joesch

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

你也有兩個相沖突的''聲明,這應該被整理出來。 – Tomalak

+0

感謝您的提醒 – joesch