XSL:使用匹配的子属性对父项属性进行分组

嘿家伙我试图使用转换XML文档直接输出到Excel表。 我遇到的问题是我需要按子节点分组元素。 我目前的XSLT是这样的:

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="ScanData"> <html> <body> <xsl:for-each select="Report/ReportHost"> <xsl:if test="ReportItem/@severity &gt; 0"> <h2><xsl:value-of select="@name"/></h2><br/> </xsl:if> <xsl:for-each select="ReportItem"> <xsl:sort select = "@severity" data-type="number" order="descending"/> <xsl:sort select = "@pluginID"/> <xsl:if test="@severity &gt; 0"> <xsl:if test="(preceding-sibling::*[1]/@pluginName != @pluginName)"> <b>Severity: </b><xsl:value-of select="@severity"/><br/> <b>Name: </b><xsl:value-of select="@pluginName"/><br/> <b>Synopsis: </b><xsl:value-of select="synopsis"/><br/> <b>Description: </b><xsl:value-of select="description"/><br/> <b>Solution: </b><xsl:value-of select="solution"/><br/> </xsl:if> Port:<xsl:value-of select="@protocol"/>/<xsl:value-of select="@port"/><br/> </xsl:if> </xsl:for-each> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet> 

示例XML

 <?xml version="1.0" ?> <?xml-stylesheet type="text/xsl" href="Internal.xsl"?> <ScanData> <Report name="Report"> <ReportHost name="192.168.1.1"> <ReportItem port="0" svc_name="general" protocol="tcp" severity="1" pluginID="11936" pluginName="OS Identification" pluginFamily="General"> <description>Using a combination of remote probes (TCP/IP, SMB, HTTP, NTP, SNMP, etc...), it is possible to guess the name of the remote operating system in use. It is also sometimes possible to guess the version of the operating system.</description> <fname>os_fingerprint.nasl</fname> <plugin_modification_date>2014/02/19</plugin_modification_date> <plugin_name>OS Identification</plugin_name> <plugin_publication_date>2003/12/09</plugin_publication_date> <plugin_type>combined</plugin_type> <risk_factor>None</risk_factor> <script_version>$Revision: 2.37 $</script_version> <solution>n/a</solution> <synopsis>It is possible to guess the remote operating system.</synopsis> </ReportItem> .....(ReportItem and ReportHost repeat with different findings and hosts) 

我的问题是,所有的数据输出每个主机地址,但我需要的数据按pluginID分组,所以而不是“主机与这些调查结果”,我需要“与这些主机的发现”。
即:
当前:
ReportHost / @名称
查找属性(名称,说明等)
受影响的端口
受影响的端口
受影响的端口
查找属性(名称,说明等)
受影响的端口

ReportHost / @名称
查找属性(名称,说明等)
受影响的端口
受影响的端口


需要:
查找属性(名称,说明等)
ReportHost / @名称
受影响的端口
受影响的端口
受影响的端口
ReportHost / @名称
受影响的端口

查找属性(名称,说明等)
ReportHost / @名称
受影响的端口
受影响的端口

我知道我说我需要它在Excel中,我已经做了一个可行的Excel的XSL我只是使用HTML为了方便testing(没有工具只是notepad ++和Firefox)。 对不起,如果我没有解释得很好。 我认为我需要使用Muenchian Grouping,因为每个组都不允许在Excel中使用,但是我是一个XML noob,我似乎无法摆脱困境。

提前致谢。

詹姆士

你确实需要在这里的Muenchian分组。 事实上,你需要使用它两次。 首先,您将通过插件对ReportItem元素进行分组,因此您可以像这样定义一个键(请注意,我已经在严重性中包括了条件,因为从现有的XSLT看,您只需要具有非零严重性的项目)

 <xsl:key name="plugin" match="ReportItem[@severity > 0]" use="@pluginID" /> 

在这个插件组中,您需要通过ReportHost对它们进行ReportHost 。 为此,您需要定义第二个键,但由于它是“组内组”,您仍需要引用该插件ID:

 <xsl:key name="plugin_by_report" match="ReportItem[@severity > 0]" use="concat(@pluginID, '|', ../@name)" /> 

请注意使用..来获取父级ReportHost元素

然后,要获取不同的插件,请使用第一个键

在这个组里面,通过ReportHost获取不同的项目,你可以这样做

 <xsl:for-each select="key('plugin', @pluginID) [generate-id() = generate-id(key('plugin_by_report',concat(@pluginID, '|', ../@name))[1])]"> 

试试这个XSL的初学者:

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output method="xml" indent="yes" /> <xsl:key name="plugin" match="ReportItem[@severity > 0]" use="@pluginID" /> <xsl:key name="plugin_by_report" match="ReportItem[@severity > 0]" use="concat(@pluginID, '|', ../@name)" /> <xsl:template match="ScanData"> <html> <body> <xsl:for-each select="Report/ReportHost/ReportItem[generate-id() = generate-id(key('plugin', @pluginID)[1])]"> <h2>Plugin: <xsl:value-of select="@pluginName"/></h2> <xsl:for-each select="key('plugin', @pluginID)[generate-id() = generate-id(key('plugin_by_report',concat(@pluginID, '|', ../@name))[1])]"> <h3>Host: <xsl:value-of select="../@name"/></h3> <xsl:apply-templates select="key('plugin_by_report',concat(@pluginID, '|', ../@name))"> <xsl:sort select = "@severity" data-type="number" order="descending"/> </xsl:apply-templates> </xsl:for-each> </xsl:for-each> </body> </html> </xsl:template> <xsl:template match="ReportItem"> <p> Port:<xsl:value-of select="@protocol"/>/<xsl:value-of select="@port"/> </p> </xsl:template> </xsl:stylesheet>