2016-03-21 28 views
2

我需要通過比較多個xmls來創建報告。有base.xml和多個分塊的xmls。實際上,這些分塊的xml被轉換爲base.xml的子集。 我的文件夾結構。比較多個xml使用for-each

Folder A - base.xml 
Folder B - metadata.xml(all the references to chuncked maintained here) 
Folder chunked - a.xml, b.xml, c.xml 

Base.xml

<SchoolRoster> 
<department> 
    <name>Science</name> 
    <location>LON</location> 
    <Student> 
     <rollNum>001</rollNum> 
     <name>John</name> 
     <age>14</age> 
     <course> 
      <refnum>A1</refnum> 
      <math>A</math> 
      <english>B</english> 
      <metas> 
       <meta> 
        <name>x</name> 
        <value>0</value> 
       </meta> 
       <meta> 
        <name>y</name> 
        <value>1</value> 
       </meta> 
       <meta> 
        <name>z</name> 
        <value>1</value> 
       </meta> 
      </metas> 
     </course> 
     <course> 
      <refnum>B1</refnum> 
      <government>A+</government> 
      <math>A</math> 
      <english>B</english> 
     </course> 
    </Student> 
    <Student> 
     <rollNum>002</rollNum> 
     <name>Tom</name> 
     <age>13</age> 
     <course> 
      <refnum>C1</refnum> 
      <gym>A</gym> 
      <geography>incomplete</geography> 
      <metas> 
       <meta> 
        <name>x</name> 
        <value>2</value> 
       </meta> 
       <meta> 
        <name>y</name> 
        <value>1</value> 
       </meta> 
      </metas> 
     </course> 
    </Student> 
</department> 
<department> 
    <name>History</name> 
    <location>OXE</location> 
    <Student> 
     <rollNum>001</rollNum> 
     <name>John</name> 
     <age>14</age> 
     <course> 
      <refnum>A1</refnum> 
      <math>A</math> 
      <english>B</english> 
      <metas> 
       <meta> 
        <name>x</name> 
        <value>0</value> 
       </meta> 
       <meta> 
        <name>y</name> 
        <value>1</value> 
       </meta> 
      </metas> 
     </course> 
     <course> 
      <refnum>B1</refnum> 
      <government>A+</government> 
      <math>A</math> 
      <english>B</english> 
     </course> 
    </Student> 
    <Student> 
     <rollNum>006</rollNum> 
     <name>Harry</name> 
     <age>13</age> 
     <course> 
      <gym>A</gym> 
      <geography>incomplete</geography> 
      <metas> 
       <meta> 
        <name>x</name> 
        <value>2</value> 
       </meta> 
       <meta> 
        <name>y</name> 
        <value>1</value> 
       </meta> 
      </metas> 
     </course> 
    </Student> 
</department> 

metadata.xml中

<metadata> 
<studentgroup category="science"> 
    <reference href="chunked/a.xml"/> 
    <reference href="chunked/b.xml"/> 
</studentgroup> 
<studentgroup category="history"> 
    <reference href="chunked/a.xml"/> 
    <reference href="chunked/c.xml"/> 
</studentgroup> 

A.XML

<learner> 
<ref>001</ref> 
<name>John</name> 
<age>14</age> 
<course> 
    <refnum>A1</refnum> 
    <math>B</math> 
    <english>B</english> 
    <metas> 
     <info> 
      <name>x</name> 
      <value>0</value> 
     </info> 
     <info> 
      <name>y</name> 
      <value>1</value> 
     </info> 
    </metas> 
</course> 
<course> 
    <refnum>B1</refnum> 
    <government>A+</government> 
    <math>A</math> 
    <english>B</english> 
</course> 

B.XML

<learner> 
<ref>002</ref> 
<name>Tom</name> 
<age>13</age> 
<course> 
    <refnum>C1</refnum> 
    <gym>A</gym> 
    <geography>incomplete</geography> 
    <metas> 
     <info> 
      <name>x</name> 
      <value>2</value> 
     </info> 
     <info> 
      <name>y</name> 
      <value>1</value> 
     </info> 
    </metas> 
</course> 

c.xml

<learner> 
<ref>006</ref> 
<name>Harry</name> 
<age>13</age> 
<course> 
    <gym>A</gym> 
    <geography>incomplete</geography> 
    <metas> 
     <info> 
      <name>x</name> 
      <value>2</value> 
     </info> 
     <info> 
      <name>y</name> 
      <value>1</value> 
     </info> 
    </metas> 
</course> 

所需的輸出:(不能夠把HTML代碼)

 Department Name  Science          
     Department Location LON          
     Roll Number   oo1    
     ---------------------------------------------------------      
           Base XML Chucked XML  Equal? 
     Name      John  John  Yes 
     Age       14   14   Yes 
     Course A1            
       Math    A   B   No 
       English    B   B   Yes 
       Meta x          
         name  x   x   Yes 
         value  0   o   Yes 
       Meta y          
         name  y   y   Yes 
         value  1   1   Yes 
     Course B1            
       Government   A+   A+   Yes 
       Math    A   A   Yes 
       English    B   B   Yes 
     ---------------------------------------------------------            
     Department Name   Science          
     Department Location  LON          
     Roll Number    oo2          
     --------------------------------------------------------- 
           Base XML Chucked XML  Equal?      
     Name      Tom   Tomcat  No 
     Age       13   13   Yes 
     Course C1            
       gym     A   A   Yes 
       geography incomplete   incomplete Yes 
       Meta x          
         name  x   x   Yes 
         value  2   2   Yes 
       Meta y          
         name  y   y   Yes 
         value  1   1   Yes 
       Meta z          
         name  z   NA   NO 
         value  1   NA   NO 
     --------------------------------------------------------- 

我嘗試以下,但不知道該怎麼辦多個for-each循環:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> 
<xsl:output method="html"/> 
<xsl:template match="/"> 
    <html> 
     <head> </head> 
     <body> 
      <xsl:apply-templates select="node()|@*"/> 
     </body> 
    </html> 
</xsl:template> 
<xsl:template match="department"> 
    <xsl:variable name="depName"> 
     <xsl:value-of select="name"/> 
    </xsl:variable> 
    <xsl:variable name="depLocation"> 
     <xsl:value-of select="location"/> 
    </xsl:variable> 
    <table style="width:100%"> 
     <tr> 
      <td>Department Name</td> 
      <td> 
       <xsl:value-of select="$depName"/> 
      </td> 
      <td/> 
      <td/> 
      <td/> 
      <td/> 
     </tr> 
     <tr> 
      <td>Department Location</td> 
      <td> 
       <xsl:value-of select="$depLocation"/> 
      </td> 
      <td/> 
      <td/> 
      <td/> 
      <td/> 
     </tr> 
     <xsl:for-each select="Student"> 
      <xsl:variable name="rollNum" select="rollNum"/> 
      <xsl:variable name="metaXML" 
       select="document('metadata.xml')/metadata/studentgroup[@category='science']/reference/@href"/> 
      <xsl:variable name="chuckedXML"/> 
      <tr> 
       <td>Roll Number</td> 
       <td> 
        <xsl:value-of select="rollNum"/> 
       </td> 
       <td> 
        <xsl:value-of select="$metaXML"/> 
       </td> 
       <td/> 
       <td/> 
       <td/> 
      </tr> 
      <tr> 
       <td/> 
       <td/> 
       <td/> 
       <td>Base XML</td> 
       <td>Chuncked XML</td> 
       <td>Equal?</td> 
      </tr> 

     </xsl:for-each> 

    </table> 
</xsl:template> 

<xsl:template match="text()"/> 

我想在這裏:

  1. 每個「部門base.xml中的/ name'與metadata.xml中的權限元數據/ studentgroup/@類別匹配。

  2. 爲每個部門/學生/ @ rollNum匹配夾頭文件'metadata/studentgroupp [@category] ​​/ reference'找到匹配的chunked xml'learner/ref'。

  3. 比較值。

  4. 類似地通過'metas/meta'標籤循環,其中'name'應該是唯一標識符。

+0

我試圖放在這裏的邏輯是: –

+0

1.對於每個'department/name',從metadata.xml中選擇正確的metadata/studentgroup/@ category。 2。爲每個部門/學生/ @ rollNum匹配夾住的文件'metadata/studentgroup/refence'找到'learner/ref'。 3.比較值。 –

+1

請使用問題下方的編輯鏈接添加新信息,而不是在評論中。 – Dijkgraaf

回答

0

這裏是爲了解決一些未拋光的嘗試中,不幸的是,輸入的樣本具有以不同的順序(agenamenameage)元件,因此,不可能簡單地基於位置比較和另外的元件名稱部分不同(metainfo),因此對於那些您需要額外模板的元素。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> 

    <xsl:param name="meta-uri" as="xs:string" select="'test2016032202.xml'"/> 
    <xsl:param name="meta-doc" as="document-node()" select="doc($meta-uri)"/> 

    <xsl:key name="cat" match="metadata/studentgroup" use="@category"/> 
    <xsl:key name="stud" match="learner" use="ref"/> 

    <xsl:key name="meta-compare" match="learner/course/metas/info" use="name"/> 

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

    <xsl:template match="/"> 
     <html> 
      <head> 
       <title>Test</title> 
      </head> 
      <body> 
       <xsl:apply-templates/> 
      </body> 
     </html> 
    </xsl:template> 

    <xsl:template match="department"> 
     <table border="1"> 
      <thead> 
       <tr> 
        <th>Department Name</th> 
        <th colspan="5"> 
         <xsl:value-of select="name"/> 
        </th> 
       </tr> 
       <tr> 
        <th>Department Location</th> 
        <th colspan="5"> 
         <xsl:value-of select="location"/> 
        </th> 
       </tr> 
      </thead> 
      <tbody> 
       <xsl:for-each select="Student"> 
        <xsl:variable name="student" select="."/> 
        <xsl:variable name="student-chunk" 
         select=" 
          for $ref-doc in document(key('cat', lower-case(../name), $meta-doc)/reference/@href) 
          return 
           key('stud', rollNum, $ref-doc)"/> 
        <tr> 
         <th>Roll Number</th> 
         <th colspan="5"> 
          <xsl:value-of select="rollNum"/> 
         </th> 
        </tr> 
        <tr> 
         <td colspan="3"/> 
         <th>Base XML</th> 
         <th>Chuncked XML</th> 
         <th>Equal?</th> 
        </tr> 
        <xsl:apply-templates select="* except rollNum"> 
         <xsl:with-param name="compare-parent" select="$student-chunk"/> 
        </xsl:apply-templates> 

       </xsl:for-each> 
      </tbody> 
     </table> 
    </xsl:template> 

    <xsl:template match="Student//*[*]"> 
     <xsl:param name="compare-parent"/> 
     <xsl:variable name="pos" as="xs:integer"> 
      <xsl:number/> 
     </xsl:variable> 
     <xsl:variable name="element-to-compare" select="$compare-parent/*[node-name(.) eq node-name(current())][$pos]"/> 
     <tr> 
      <td colspan="2"/> 
      <th colspan="4"> 
       <xsl:value-of select="local-name()"/> 
      </th> 
     </tr> 
     <xsl:apply-templates select="*"> 
      <xsl:with-param name="compare-parent" select="$element-to-compare"></xsl:with-param> 
     </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="Student//*[not(*)]"> 
     <xsl:param name="compare-parent"/> 
     <xsl:variable name="pos" as="xs:integer"> 
      <xsl:number/> 
     </xsl:variable> 
     <xsl:variable name="element-to-compare" 
      select="$compare-parent/*[node-name(.) eq node-name(current())][$pos]"/> 
     <tr> 
      <td colspan="2"/> 
      <th> 
       <xsl:value-of select="local-name()"/> 
      </th> 
      <td> 
       <xsl:value-of select="."/> 
      </td> 
      <td> 
       <xsl:value-of select="$element-to-compare"/> 
      </td> 
      <td> 
       <xsl:value-of select=". = $element-to-compare"/> 
      </td> 
     </tr> 
    </xsl:template> 

    <xsl:template match="Student/course/metas/meta" priority="5"> 
     <xsl:param name="compare-parent"/> 
     <xsl:variable name="element-to-compare" select="key('meta-compare', name, $compare-parent)"/> 
     <tr> 
      <td colspan="3" align="right"> 
       <xsl:value-of select="name"/> 
      </td> 
      <td> 
       <xsl:value-of select="value"/> 
      </td> 
      <td> 
       <xsl:value-of select="$element-to-compare/value"/> 
      </td> 
      <td> 
       <xsl:value-of select="value = $element-to-compare/value"/> 
      </td> 
     </tr> 
    </xsl:template> 

</xsl:stylesheet> 
+0

太棒了!感謝您提供解決方案。這將需要一段時間來理解,並將其實施到我的真實場景。我可能有幾個問題。非常感謝。 –

+0

如何選擇不匹配的密鑰。如果我在a.xml中添加另一個標記 xyz abc,如何在我的chuncked XML列中打印它。如果我使用,它選擇當前節點而不選擇鑰匙。 –