使用for-each比较多个xmls

时间:2016-03-21 21:54:15

标签: xslt xslt-1.0 xslt-2.0

我需要通过比较多个xmls来创建报告。有base.xml和多个chunked xmls。实际上这些chunked xmls是base.xml的转换子集。 我的文件夹结构。

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

我正在尝试关注但不确定如何为每个循环执行多个操作:

 <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中的每个“部门/名称”,匹配metadata.xml中的正确元数据/ studentgroup / @类别。

  2. 为每个部门/学生/ @ rollNum匹配chucked文件'metadata / studentgroupp [@category] ​​/ reference'找到匹配的chunked xml'learningner / ref'。

  3. 比较值。

  4. 同样循环遍历'metas / meta'标签,其中'name'应该是唯一标识符。

1 个答案:

答案 0 :(得分: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>