2013-08-31 18 views
6

Używam XSL do odczytu w trzech dokumentach XML, które są identyczne, z wyjątkiem ich atrybutów mają różne wartości (potencjalnie będę czytać wiele plików XML). Chcę policzyć liczbę razy, gdy atrybut "wynikowy" ma wartość "Przekazywane" lub "Nieudane" dla elementu, którego atrybut "testName" = "TestOne". Ja to osiągnąć stosując następujący:Jak przetwarzać wszystkie dane z wielu plików XML po scaleniu przy użyciu 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> 

Wynik produkuje 3 sumy tabele. Moim zamiarem jest wyświetlenie jednej tabeli Sumy wyświetlającej ile razy testOne przeszedł i nie powiodło się we wszystkich dokumentach XML. Wygląda na to, że każdy dokument XML jest czytany/zaznaczany, a następnie przetwarzany pojedynczo. Chciałbym przeczytać i wybrać wszystkie pliki XML przed ich przetworzeniem.

Odpowiedz

9

Można zbierać wszystkie się Result elementy z całej trzech dokumentów przy użyciu coś jak

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

predykaty, a następnie zastosować do tego policzyć elementy, które Cię interesują, np

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

Zamiast ustalonego zestawu nazw plików, jeśli masz główny plik index.xml zawierający listę wszystkich plików, które chcesz połączyć, na przykład:

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

następnie można użyć tego wskaźnika jako główne wejście do arkusza stylów i zmienna allResults staje:

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

Po przejechaniu węzła ustawiony na funkcję document przybiera wartość ciągu każdego węzła z kolei traktuje to jako URI pliku do załadowania, zwracając wynikowy zbiór węzłów głównego dokumentu.

Oto pełna przykład

<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

Odmianą pierwotnego pytania wykorzystuje plik o nazwie „index.xml” zawierający odnośniki do wszystkich plików XML do procesu (może być setki) z modyfikacją do merge2.xsl.Jak osiągnąć zamierzony rezultat dzięki tej nowej wariacji? – user2734805

+0

@ user2734805 jest to w rzeczywistości prostsze niż w przypadku stałych nazw plików - zobacz moją edycję. –

+0

Ian - Twój przykład zadziałał dla mnie. Pojęcie "zestawu węzłów" było tym, czego mi brakowało. Dziękuję Ci. – user2734805

0

To jest prawie taki sam jak wyżej, ale bez zmiennej.

<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

Nie, będzie to miało taki sam efekt jak oryginalny arkusz stylów w pytaniu, tworząc osobną liczbę dla każdego pliku, a nie pojedynczą liczbę agregatów dla wszystkich plików. –

+1

całkiem słusznie - przepraszam, spałem z otwartymi oczami. –

Powiązane problemy