2010-11-20 20 views
0

我有一個xml中的術語列表。條款或者有termtype nd或者pt。如果一個術語是termtype nd,它沒有ID,而是引用一個termtype PT,它有一個ID。我需要做兩件事。xslt查找並插入或用增量編號替換

  1. 用TermType nd的增量編號替換termId值的XXX,所以所有的術語都有一個id。

  2. 其中termType ND引用termType PT,我需要以某種方式尋找其ID,並插入:


<Zthes> 
<term> 
<termName>Term 1</termName> 
<termId>insert new term id N+1 </termId> 
<termType>Nd</termType> 

<relation> 
<relationType>USE</relationType> 
<termId>insert ID of term 2 <termID> 
<termName>Term2</termName> 
</relation> 
</term> 

<term> 
<termName>Term 2</termName> 
<termId>587889</termId> 
<termType>pt</termType> 
</term> 

</zthes> 

任何人都可以給我如何做到這一點的指針。我對xslt一無所知。我在這裏找到並找到了關於查找和替換Unique的內容,但從我所瞭解的答案中,我認爲它不適用。

同樣,它不一定是xslt。我和一位開發人員合作,他說這是做這件事的最好方式,但答案太微不足道,他不願意去做。雖然對我來說太困難了!

+0

(1)是「termName」內部「關係」將成爲「termName」的精確副本在主術語? (上面有空白區別)(2)對於生成的termId值,它們是從1開始,從文檔中的最高termId還是從其他指定值開始? – Erica 2010-11-20 10:27:58

+0

是的,他們將被精確複製,並且termid值可以從1開始。對不起,我應該說清楚。 – Charlie 2010-11-20 10:44:57

回答

0

變換

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="ktermPtIdByName" 
     match="term[termType='pt']/termId" 
     use="../termName"/> 

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

<xsl:template match="term[termType='Nd']/termId"> 
    <termId> 
    <xsl:number level="single" count="/*/term[termType='Nd']"/> 
    </termId> 
</xsl:template> 

<xsl:template match="relation/termId"> 
    <termId> 
    <xsl:value-of select="key('ktermPtIdByName', ../termName)"/> 
    </termId> 
</xsl:template> 
</xsl:stylesheet> 

當施加在下面的XML文檔(您的XML但校正爲語法結構良好的和語義正確的,那麼放大兩次以進行更有趣):

<zthes> 
    <term> 
     <termName>Term 1</termName> 
     <termId></termId> 
     <termType>Nd</termType> 
     <relation> 
      <relationType>USE</relationType> 
      <termId></termId> 
      <termName>Term 2</termName> 
     </relation> 
    </term> 
    <term> 
     <termName>Term 2</termName> 
     <termId>587889</termId> 
     <termType>pt</termType> 
    </term> 
    <term> 
     <termName>Term 3</termName> 
     <termId></termId> 
     <termType>Nd</termType> 
     <relation> 
      <relationType>USE</relationType> 
      <termId></termId> 
      <termName>Term 4</termName> 
     </relation> 
    </term> 
    <term> 
     <termName>Term 4</termName> 
     <termId>587890</termId> 
     <termType>pt</termType> 
    </term> 
</zthes> 

產生想要的,正確的結果

<zthes> 
    <term> 
     <termName>Term 1</termName> 
     <termId>1</termId> 
     <termType>Nd</termType> 
     <relation> 
     <relationType>USE</relationType> 
     <termId>587889</termId> 
     <termName>Term 2</termName> 
     </relation> 
    </term> 
    <term> 
     <termName>Term 2</termName> 
     <termId>587889</termId> 
     <termType>pt</termType> 
    </term> 
    <term> 
     <termName>Term 3</termName> 
     <termId>2</termId> 
     <termType>Nd</termType> 
     <relation> 
     <relationType>USE</relationType> 
     <termId>587890</termId> 
     <termName>Term 4</termName> 
     </relation> 
    </term> 
    <term> 
     <termName>Term 4</termName> 
     <termId>587890</termId> 
     <termType>pt</termType> 
    </term> 
</zthes> 

請注意

  1. 身份規則用於每個節點複製 「原樣」。

  2. 模板僅針對需要修改的元素覆蓋身份規則。

  3. <xsl:number>用於(我懶)計算所需的termId。

  4. 甲密鑰被用於最有效的查找termId由其TermName

+0

這真是太棒了,完美的作品,非常感謝你 – Charlie 2010-11-20 18:39:20

+0

+1非常好的答案。 – 2010-11-20 22:35:46

+0

非常好!是否有辦法使它適應,以便它處理引用其他'Nd'術語的'Nd'術語(即,在解決關係之前確保所有'Nd'術語都可以具有有效的ID?) – Erica 2010-11-21 01:16:40

0

我正在閱讀一些內容,但我想我知道你在做什麼。

我建議用兩個單獨的XSL來做這件事。將兩個XSL傳遞組合成一個XSL當然是可能的,但實際實現方式因您所使用的XSL庫而異(這裏有一些細節,如果您好奇:http://www.oreillynet.com/xml/blog/2006/08/multistage_xslt_scripts.html

第一遍應該去通過你所有的條件,並將數字分配給標記爲「Nd」的數字。我猜:

(一),一旦他們有一個ID,他們應該有自己的類型變更爲「PT」,並

(b)將這些元素的順序是不特定的。

我建議這樣做的一個單獨的通道的原因是,你的一個術語可能引用另一個本身是'Nd'類型的術語。如果是這樣的話,那麼它不會有一個有效的數字來引用(因爲沒有人會一直尚未分配)

的XSL執行此步驟是這樣的:

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

    <xsl:template match="term[termType = 'Nd']"> 
     <term> 
      <xsl:copy-of select="termName"/> 
      <termId><xsl:value-of select="position()"/></termId> 
      <termType>pt</termType> 
      <xsl:copy-of select="relation" /> 
     </term> 
    </xsl:template> 

    <xsl:template match="/"> 
     <zthes> 
      <xsl:apply-templates select="zthes/term[termType = 'Nd']"/> 
      <xsl:copy-of select="zthes/term[termType = 'pt']"/> 
     </zthes> 
    </xsl:template> 

</xsl:stylesheet> 

的第二步是獲取該變換的輸出,並通過第二次變換將其「填充」「關係」項的ID。這是一個相當直接的身份(確切的遞歸複製)轉換,其中有一條特殊規則。特殊規則標識關係節點內的termIds,並根據名稱匹配在正確的termId中進行替換。這個變換看起來像這樣:

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

    <xsl:template match="relation/termId"> 
     <termId> 
      <xsl:value-of select="/zthes/term[termName=current()/../termName]/termId"/> 
     </termId> 
    </xsl:template> 

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

</xsl:stylesheet> 

我希望這會大致做你以後的事情。它不會像你當前的輸入數據那樣工作,因爲你當前的輸入實際上是無效的xml。 :)要修復它:

  • 將開始標記 開始標記中的'Zthes'更改爲'zthes'。XML區分大小寫
  • 在第一個'關係'塊中,確保關閉'termId' 節點。目前你打開 兩次,而不是關閉它。
  • 在「關係」塊的「termName」中,當您的意思是「第2期」時,您引用了「Term2」 。 有一個空格區別, 會阻止它們匹配。

祝你好運!

+0

非常感謝!那真是太好了,我非常感謝你的幫助。 – Charlie 2010-11-20 18:41:00