Hier ist eine XSLT 2.0-Methode.
Unter der Annahme, dass eine Sequenz von Dokumentknoten enthält, die Sie scannen möchten, möchten Sie für jedes Element, das in den Dokumenten angezeigt wird, eine Zeile erstellen. Sie können <xsl:for-each-group>
verwenden zu tun, dass:
<xsl:for-each-group select="$docs//*" group-by="name()">
<xsl:sort select="current-group-key()" />
<xsl:variable name="name" as="xs:string" select="current-grouping-key()" />
<xsl:value-of select="$name" />
...
</xsl:for-each-group>
Dann wollen Sie die Statistiken zu den Unterlagen für dieses Element herausfinden. Zuerst finden die Dokumente in ihnen ein Element dieses Namens haben:
<xsl:variable name="docs-with" as="document-node()+"
select="$docs[//*[name() = $name]" />
Zweitens müssen Sie eine Sequenz von der Anzahl der Elemente dieses Namens in jedem der Dokumente:
<xsl:variable name="elem-counts" as="xs:integer+"
select="$docs-with/count(//*[name() = $name])" />
Und jetzt Sie können die Berechnungen durchführen. Durchschnitt, Minimum und Maximum können mit den Funktionen avg()
, min()
und max()
berechnet werden. Der Prozentsatz ist einfach die Anzahl der Dokumente, die das Element enthalten, dividiert durch die Gesamtzahl der formatierten Dokumente.
Putting, dass zusammen:
<xsl:for-each-group select="$docs//*" group-by="name()">
<xsl:sort select="current-group-key()" />
<xsl:variable name="name" as="xs:string" select="current-grouping-key()" />
<xsl:variable name="docs-with" as="document-node()+"
select="$docs[//*[name() = $name]" />
<xsl:variable name="elem-counts" as="xs:integer+"
select="$docs-with/count(//*[name() = $name])" />
<xsl:value-of select="$name" />
<xsl:text>* </xsl:text>
<xsl:value-of select="format-number(avg($elem-counts), '#,##0.0')" />
<xsl:text> </xsl:text>
<xsl:value-of select="format-number(min($elem-counts), '#,##0')" />
<xsl:text> </xsl:text>
<xsl:value-of select="format-number(max($elem-counts), '#,##0')" />
<xsl:text> </xsl:text>
<xsl:value-of select="format-number((count($docs-with) div count($docs)) * 100, '#0')" />
<xsl:text>%</xsl:text>
<xsl:text>
</xsl:text>
</xsl:for-each-group>
Was habe ich hier noch nicht fertig ist zerklüftet die Linien entsprechend der Tiefe des Elements. Ich habe gerade die Elemente alphabetisch sortiert, um Ihnen Statistiken zu geben. Dafür gibt es zwei Gründe: Erstens ist es wesentlich schwieriger (wie zu aufwendig, hier zu schreiben), die Elementstatistiken in einer Art Struktur darzustellen, die ihre Darstellung in den Dokumenten widerspiegelt, nicht zuletzt, weil verschiedene Dokumente unterschiedliche Strukturen haben können. Zweitens kann in vielen Markup-Sprachen die genaue Struktur der Dokumente nicht bekannt sein (weil beispielsweise Abschnitte innerhalb von Abschnitten in beliebiger Tiefe verschachtelt werden können).
Ich hoffe, es ist dennoch nützlich.
UPDATE:
die XSLT-Wrapper benötigen und einige Anweisungen für XSLT ausgeführt wird? OK. Holen Sie zuerst Ihre Hände auf Saxon 9B.
Sie müssen alle Dateien, die Sie analysieren möchten, in ein Verzeichnis einfügen. Mit Saxon können Sie auf alle Dateien in diesem Verzeichnis (oder seinen Unterverzeichnissen) zugreifen, indem Sie eine Sammlung mit einer special URI syntax verwenden. Es lohnt sich, sich diese Syntax anzuschauen, wenn Sie rekursiv recherchieren oder die Dateien, die Sie sehen, nach ihrem Dateinamen filtern möchten.
Nun ist die vollständige XSLT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:param name="dir" as="xs:string"
select="'file:///path/to/default/directory?select=*.xml'" />
<xsl:output method="text" />
<xsl:variable name="docs" as="document-node()*"
select="collection($dir)" />
<xsl:template name="main">
<xsl:for-each-group select="$docs//*" group-by="name()">
<xsl:sort select="current-group-key()" />
<xsl:variable name="name" as="xs:string" select="current-grouping-key()" />
<xsl:variable name="docs-with" as="document-node()+"
select="$docs[//*[name() = $name]" />
<xsl:variable name="elem-counts" as="xs:integer+"
select="$docs-with/count(//*[name() = $name])" />
<xsl:value-of select="$name" />
<xsl:text>* </xsl:text>
<xsl:value-of select="format-number(avg($elem-counts), '#,##0.0')" />
<xsl:text> </xsl:text>
<xsl:value-of select="format-number(min($elem-counts), '#,##0')" />
<xsl:text> </xsl:text>
<xsl:value-of select="format-number(max($elem-counts), '#,##0')" />
<xsl:text> </xsl:text>
<xsl:value-of select="format-number((count($docs-with) div count($docs)) * 100, '#0')" />
<xsl:text>%</xsl:text>
<xsl:text>
</xsl:text>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Und es laufen Sie würde so etwas tun:
> java -jar path/to/saxon.jar -it:main -o:report.txt dir=file:///path/to/your/directory?select=*.xml
Dies sagt Saxon den Prozess mit der Vorlage main
Namen zu starten, setzen die dir
Parameter auf file:///path/to/your/directory?select=*.xml
und senden Sie den Ausgang an report.txt
.
Jeni, ich bin ein großer Fan von dir, da deine Seite mir bei vielen Herausforderungen mit XPath geholfen hat. Ich bin froh, dass Sie bei uns hier bei StackOverflow sind. –
Habe dein Update gesehen - jetzt bekomme ich es :) –