2013-08-31 15 views
6

Ich benutze XSL zum Einlesen von drei XML-Dokumente, die identisch sind, außer ihre Attribute haben unterschiedliche Werte (möglicherweise werde ich viele XML-Dateien lesen). Ich möchte zählen, wie oft das Attribut "outcome" den Wert "Passed" oder "Failed" für das Element hat, dessen Attribut "testName" = "TestOne" ist. Ich bin, dies zu erreichen mit dem folgenden:So verarbeiten Sie alle Daten aus mehreren XML-Dateien nach dem Zusammenführen mit XSL

file1.xml

<container> 
    <build> 
     <Tests> 
      <Results> 
       <Result testName="TestOne" outcome="Passed" ></Result> 
       <Result testName="TestTwo" outcome="Passed" ></Result> 
      </Results> 
     </Tests>  
    </build> 
</container> 

File2.xml

<container> 
    <build> 
     <Tests> 
      <Results> 
       <Result testName="TestOne" outcome="Passed" ></Result> 
       <Result testName="TestTwo" outcome="Failed" ></Result> 
      </Results> 
     </Tests>  
    </build> 
</container> 

File3.xml

<container> 
    <build> 
     <Tests> 
      <Results> 
       <Result testName="TestOne" outcome="Failed" ></Result> 
       <Result testName="TestTwo" outcome="Failed" ></Result> 
      </Results> 
     </Tests>  
    </build> 
</container> 

Index.xml

<?xml-stylesheet type="text/xsl" href="merge3.xsl"?> 
<list> 
    <entry name="File1.xml" /> 
    <entry name="File2.xml" /> 
    <entry name="File3.xml" /> 
</list> 

Merge2.xsl

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

<xsl:template match="/"> 
    <xsl:for-each select="/list/entry"> 
     <xsl:apply-templates select="document(@name)/container/build/*[local-name()='Tests']" /> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template match="*[local-name()='Results']"> 
    <xsl:variable name="name" select="'TestOne'" /> 
    <xsl:variable name="totalPassed" select="*[local-name()='Result'][@testName = 'TestOne'][@outcome = 'Passed']" /> 
    <xsl:variable name="totalFailed" select="*[local-name()='Result'][@testName = 'TestOne'][@outcome = 'Failed']" /> 

    <h2>Totals</h2> 
    <table border="1" cellSpacing="0" cellPadding="5" > 
     <tr bgcolor="#9acd32"> 
      <th>Test Name</th> 
      <th>Total Passed</th> 
      <th>Total Failed</th> 
     </tr> 
     <tr> 
      <td><xsl:value-of select="$name"/></td> 
      <td><xsl:value-of select="count($totalPassed)"/></td> 
      <td><xsl:value-of select="count($totalFailed)"/></td> 
     </tr> 
    </table> 
</xsl:template> 

</xsl:stylesheet> 

Das Ergebnis erzeugt 3 Summentabellen. Ich beabsichtige, eine Totals-Tabelle anzuzeigen, die anzeigt, wie oft TestOne in allen XML-Dokumenten bestanden und nicht bestanden hat. Es scheint, dass jedes XML-Dokument gelesen/ausgewählt und dann einzeln verarbeitet wird. Ich möchte alle XML-Dateien einlesen und auswählen, bevor Sie sie verarbeiten.

Antwort

9

Sie könnten alle die Result Elemente aus allen drei Dokumente sammeln so etwas wie

<xsl:variable name="allResults" 
    select="(/ | document('file2.xml') | document('file3.xml'))//Result" /> 

und anschließend Prädikate diese anwenden, um die Elemente, die Sie interessiert sind zu zählen, zum Beispiel

<xsl:value-of select=" 
    count($allResults[@testName = 'TestOne'][@outcome = 'Failed'])" /> 

Anstelle einer festen Menge von Dateinamen, wenn Sie eine Haupt index.xml haben, die alle Dateien auflistet, die Sie kombinieren möchten, zum Beispiel:

<list> 
    <entry name="File1.xml" /> 
    <entry name="File2.xml" /> 
    <entry name="File3.xml" /> 
</list> 

dann können Sie diesen Index als Haupteingang zu Ihrem Stylesheet verwenden und die allResults Variable wird:

<xsl:variable name="allResults" 
    select="document(/list/entry/@name)//Result" /> 

Wenn Sie einen Knoten auf der document Funktion übergeben es nimmt den String-Wert jedes Knotens der Reihe nach und behandelt, dass als der URI einer Datei zu laden, die resultierende des Dokuments Stammknoten zurückgegeben.

Hier ist ein komplettes Beispiel

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

    <xsl:variable name="allResults" 
    select="document(/list/entry/@name)//Result" /> 

    <xsl:template match="/"> 
    <xsl:variable name="name" select="'TestOne'" /> 

    <h2>Totals</h2> 
    <table border="1" cellSpacing="0" cellPadding="5" > 
     <tr bgcolor="#9acd32"> 
      <th>Test Name</th> 
      <th>Total Passed</th> 
      <th>Total Failed</th> 
     </tr> 
     <tr> 
      <td><xsl:value-of select="$name"/></td> 
      <td><xsl:value-of select="count($allResults[@testName = $name] 
               [@outcome = 'Passed'])"/></td> 
      <td><xsl:value-of select="count($allResults[@testName = $name] 
               [@outcome = 'Failed'])"/></td> 
     </tr> 
    </table> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Eine Variation der ursprünglichen Frage verwendet eine Datei „index.xml“ genannt Verweise auf alle XML-Dateien zu verarbeiten enthält, mit einer Änderung merge2.xsl (könnten Hunderte sein).Wie würde man mit dieser neuen Variante das beabsichtigte Ergebnis erreichen? – user2734805

+0

@ user2734805 das ist eigentlich einfacher als der Fall von festen Dateinamen - siehe meine Bearbeitung. –

+0

Ian - Dein Beispiel hat bei mir funktioniert. Das Konzept eines "Knotensets" war das Stück, das mir fehlte. Vielen Dank. – user2734805

0

Diese fast das gleiche wie oben, aber ohne eine Variable.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="html"/> 
<xsl:template match="/"> 
    <h2>Totals</h2> 
    <table border="1" cellSpacing="0" cellPadding="5" > 
     <tr bgcolor="#9acd32"> 
      <th>Test Name</th> 
      <th>Total Passed</th> 
      <th>Total Failed</th> 
     </tr> 
     <xsl:for-each select="/list/entry"> 
      <tr> 
      <td><xsl:value-of select="@name"/></td> 
      <td><xsl:value-of select="count(document(@name)/container/build/Tests/Results/Result[@outcome eq 'Passed'])"/></td> 
      <td><xsl:value-of select="count(document(@name)/container/build/Tests/Results/Result[@outcome eq 'Failed'])"/></td> 
      </tr> 
     </xsl:for-each> 
    </table> 
</xsl:template> 

</xsl:stylesheet> 
+0

Nein, das hat den gleichen Effekt wie das ursprüngliche Stylesheet in der Frage, wobei für jede Datei eine separate Anzahl erstellt wird und nicht eine einzelne Aggregatzählung für alle Dateien. –

+1

ganz richtig - Entschuldigung, ich habe mit offenen Augen geschlafen. –

Verwandte Themen