2014-11-22 41 views
0

我輸入的是:重命名和發送基於在子節點元素的值的所有子節點XSLT

<Recordset> 
     <Report_ID> 
     <Record> 
      <Report_ID>A1</Report_ID> 
      <name1>a1</name1> 
      <name2>a1</name2> 
      <name3>a1</name3> 
      <name4>true</name4> 
     </Record> 
     <Record> 
      <Report_ID>A1</Report_ID> 
      <name1>a1</name1> 
      <name2>b1</name2> 
      <name3>t1</name3> 
      <name4>false</name4> 
     </Record> 
     <Record> 
      <Report_ID>A1</Report_ID> 
      <name1>a1</name1> 
      <name2>a1</name2> 
      <name3>a1</name3> 
      <name4>false</name4> 
     </Record> 
    </Report_ID> 
    <Report_ID> 
     <Record> 
     <Report_ID>B1</Report_ID> 
     <name1>a1</name1> 
     <name2>a1</name2> 
     <name3>a1</name3> 
     <name4>true</name4> 
    </Record> 
    <Record> 
     <Report_ID>B1</Report_ID> 
     <name1>a1</name1> 
     <name2>a1</name2> 
     <name3>a1</name3> 
     <name4>true</name4> 
    </Record> 
    </Report_ID> 
</Recordset> 

起初我有一個下REPORT_ID,我已經通過獨特的REPORT_ID分組的多條記錄。接下來,我想實現以下目標:

目標:如果在一個Report_ID中,name4中的任何一個爲「false」,則該Report_Id下的所有記錄都應該去,並且父節點應重命名爲Report_ID_Complicated,如果所有name4值都爲true那麼它應該重命名爲Report_ID_Simple。分組很好...必須有另一個檢查條件,並且相應地重命名父節點。

<Recordset> 
     <Report_ID_Complicated> 
     <Record> 
      <Report_ID>A1</Report_ID> 
      <name1>a1</name1> 
      <name2>a1</name2> 
      <name3>a1</name3> 
      <name4>true</name4> 
     </Record> 
     <Record> 
      <Report_ID>A1</Report_ID> 
      <name1>a1</name1> 
      <name2>b1</name2> 
      <name3>t1</name3> 
      <name4>false</name4> 
     </Record> 
     <Record> 
      <Report_ID>A1</Report_ID> 
      <name1>a1</name1> 
      <name2>a1</name2> 
      <name3>a1</name3> 
      <name4>false</name4> 
     </Record> 
    </Report_ID_Complicated> 
    <Report_ID_Simple> 
     <Record> 
     <Report_ID>B1</Report_ID> 
     <name1>a1</name1> 
     <name2>a1</name2> 
     <name3>a1</name3> 
     <name4>true</name4> 
    </Record> 
    <Record> 
     <Report_ID>B1</Report_ID> 
     <name1>a1</name1> 
     <name2>a1</name2> 
     <name3>a1</name3> 
     <name4>true</name4> 
    </Record> 
    </Report_ID_Simple> 
</Recordset> 

UPDATE:

蒂姆的答案的作品完美,但我寫的波紋管代碼組的報告ID現在,當我試圖用我以前的代碼合併添的回答我得到「一個XSTL - 每個元素不得包含xsl:template元素「

我相信我們不能在每個模板中應用模板,所以如果你能指出我正確的方向,可以合併這兩個代碼。

我的XSLT代碼:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:key name="kReport_Id" match="Record" use="Report_Id"/> 
<xsl:key name="kname4" match="Record" use="concat(Report_Id,name4)"/> 
<xsl:template match="/"> 
    <ns:File_Intermediate> 
     <xsl:for-each select="ns:File/RecordSet/Record[generate-id() = generate-id(key('kReport_Id',Report_Id))]"> 
      <Report_Id> 
       <ReportID_Simple> 
        <xsl:variable name="vReport_Id" select="Report_Id"/> 
        <xsl:for-each select="../Record[Report_Id = $vReport_Id][generate-id() = generate-id(key('kname4',concat(Report_Id,name4)))]"> 
         <xsl:for-each select="../Record[Report_Id = $vReport_Id][name4=current()/name4]"> 
          <xsl:variable name="name4" select="name4"/> 
          <xsl:if test="name4='true'"> 
           <xsl:copy-of select="."/> 
          </xsl:if> 
         </xsl:for-each> 
        </xsl:for-each> 
       </ReportID_Simple> 
       <ReportID_Complicated> 
        <xsl:variable name="vReport_Id" select="Report_Id"/> 
        <xsl:for-each select="../Record[Report_Id = $vReport_Id][generate-id() = generate-id(key('kname4',concat(Report_Id,name4)))]"> 
         <xsl:for-each select="../Record[Report_Id = $vReport_Id][name4=current()/name4]"> 
          <xsl:variable name="name4" select="name4"/> 
          <xsl:if test="name4='false'"> 
           <xsl:copy-of select="."/> 
          </xsl:if> 
         </xsl:for-each> 
        </xsl:for-each> 
       </ReportID_Complicated> 
      </Report_Id> 
     </xsl:for-each> 
    </ns:File_Intermediate> 
    </xsl:template> 
</xsl:stylesheet> 
+1

您是否嘗試過的東西?你的XSLT在哪裏? – 2014-11-22 12:31:20

回答

2

首先,您需要與XSLT identity template,其自身的副本在XML所有節點,是

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

開始這只是意味着你需要爲希望轉換的節點編寫模板。您想將Report_ID元素更改爲Report_ID_Complicated,其中有Record,其中name4爲false。這意味着你只需要一個模板來匹配這樣的記錄

<xsl:template match="Recordset/Report_ID[Record/name4 = 'false']"> 

注意使用前Recordset的,因爲在XML嵌套Report_ID

的內容將類似於身份模板,除非你可以明確地創建一個新的節點,而不是複製現有的一個

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

對於其他的模板,你可以再搭配相反:

<xsl:template match="Recordset/Report_ID[not(Record/name4 = 'false')]"> 

請注意,這樣寫第二個模板是不正確的。

<xsl:template match="Recordset/Report_ID"> 

這是因爲XSLT認爲它與上一個優先級相同,這是一個錯誤,所以您需要額外的xpath條件來區分它。此外,請注意,如果你有,只是這種相匹配的模板......

<xsl:template match="Report_ID"> 

這將有一個較低的優先級,這將是可以接受的,但在你的XML的情況下,你有嵌套Report_ID元素,它也會匹配(感謝Lingamurthy CS指出這一點!)

試試這個XSLT

<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="Recordset/Report_ID[Record/name4 = 'false']"> 
     <Report_ID_Complicated> 
     <xsl:apply-templates select="@*|node()"/> 
     </Report_ID_Complicated> 
    </xsl:template> 

    <xsl:template match="Recordset/Report_ID[not(Record/name4 = 'false')]"> 
     <Report_ID_Simple> 
     <xsl:apply-templates select="@*|node()"/> 
     </Report_ID_Simple> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Tim C,它不應該警告Report_ID的「模糊」模板,因爲有兩個模板匹配它。我不確定我是否有道理。我會在一個模板中使用'xsl:choose'來處理這兩種ReportID .. – 2014-11-22 14:39:49

+0

@LingamurthyCS沒有歧義。兩個模板匹配不同的節點。第一個包含'Record/name4 ='false''孩子,第二個包含所有其他人。與''一起工作實際上是處理這種情況的劣勢方式。 – Tomalak 2014-11-22 14:41:35

+0

它的工作原理..但是,在所有應有的尊重,匹配'Report_ID'的最後一個模板應該與'Record/name4 ='false''的Report_ID's匹配,對吧?(我只是想讓我的概念正確)..順便說一句,更正..有更多的後代名爲'Report_ID' ..匹配應該是'Recordset/Report_ID' .. – 2014-11-22 14:45:37

相關問題