2014-01-15 93 views
2

輸入XML:XSLT 1.0模板與模式屬性

<?xml version="1.0" encoding="utf-8"?> 
<Root> 
    <text> 
     <body> 
     <head>title1</head> 
     <div n="1"> 
      <head>title2</head> 
      <div n="1.1"> 
       <head>title3</head> 
       <p>xyz</p> 
       <p>xyz</p> 
      </div> 
      <div n="1.2"> 
       <head>title4</head> 
       <p>xyz</p> 
       <p>xyz</p> 
       <div n="1.2.1"> 
        <p>xyz</p> 
        <p>xyz</p> 
       </div> 
      </div> 
     </div> 
     </body> 
    </text> 
</Root> 

我想添加屬性「ID = 1」至所有<div>元素和屬性「電平= 0」,其具有<div>沒有<div>孩子。

這是我的實際XSLT:

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

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

<xsl:template match="body//div"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()[not(descendant::div)]" mode="level"/> 
     <xsl:apply-templates select="node()[descendant::div]" mode="id"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="body//div[not(descendant::div)]" mode="level"> 
    <xsl:copy> 
     <xsl:for-each select="."> 
      <xsl:attribute name="id">1</xsl:attribute> 
      <xsl:attribute name="level">0</xsl:attribute> 
     </xsl:for-each> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="body//div[descendant::div]" mode="id"> 
    <xsl:copy> 
     <xsl:for-each select="."> 
      <xsl:attribute name="id">1</xsl:attribute> 
     </xsl:for-each> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

模板與模式= 「ID」 必須匹配<div>元素與<div>孩子(添加屬性 「ID」),與模式模板= 「水平」 應該匹配沒有<div>孩子的元素(同時添加attribut「id」和「level」)。但由於某種原因,我得到了一些<div>(那些n = 1和n = 1.2.1)沒有被任何模板處理。

實際輸出XML:

<?xml version="1.0" encoding="UTF-8"?> 
<Root> 
    <text> 
     <body> 
     <head>title1</head> 
     <div> 
      title2 
      <div id="1" level="0" n="1.1"> 
       <head>title3</head> 
       <p>xyz</p> 
       <p>xyz</p> 
      </div> 

      <div id="1" n="1.2"> 
       <head>title4</head> 
       <p>xyz</p> 
       <p>xyz</p> 
       <div> 
        xyz 
        xyz 
       </div> 
      </div> 
     </div> 
     </body> 
    </text> 
</Root> 

我敢肯定,我正在做一些奇怪的錯誤(也許在使用模板的使用模式?),但到目前爲止,還沒有發現它。任何建議將非常感激。 謝謝大家。

回答

4

我不完全確定你爲什麼首先使用模式。下面的解決方案只需使用「常用」模板即可實現您想要的功能。

帶模式的模板專爲迭代樹不止一次而設計,因此可以訪問和處理節點兩次或更多次。

通常,儘可能少地打斷身份轉換。這就是爲什麼下面的樣式匹配

  • div元素與div兒童(div[div]
  • 沒有他們(div[not(div)]

適用最小的變化,然後返回節點的剩餘身份再次與apply-templates轉換。

注意:這適合您顯示的輸入XML。然而,以使其與您的實際輸入工作,你可能有

<xsl:template match="div[div]"> 

<xsl:template match="div[descendant::div]"> 

根據您的輸入結構發生改變。

樣式表

<?xml version="1.0" encoding="utf-8"?> 

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output method="xml" indent="yes"/> 

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

<xsl:template match="div[div]"> 
    <xsl:copy> 
    <xsl:attribute name="id">1</xsl:attribute> 
    <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="div[not(div)]"> 
    <xsl:copy> 
    <xsl:attribute name="id">1</xsl:attribute> 
    <xsl:attribute name="level">0</xsl:attribute> 
    <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

輸出

<?xml version="1.0" encoding="UTF-8"?> 
<Root> 
<text> 
    <body> 
    <head>title1</head> 
    <div id="1"> 
     <head>title2</head> 
     <div id="1" level="0"> 
      <head>title3</head> 
      <p>xyz</p> 
      <p>xyz</p> 
     </div> 
     <div id="1"> 
      <head>title4</head> 
      <p>xyz</p> 
      <p>xyz</p> 
      <div id="1" level="0"> 
       <p>xyz</p> 
       <p>xyz</p> 
      </div> 
     </div> 
    </div> 
    </body> 
</text> 
</Root>