В целях продвижения вперед рассмотрим следующую таблицу стилей:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="staff-by-center" match="Staff/Items/Item" use="@StaffCenter"/>
<xsl:key name="workgroup-by-center" match="Workgroup/Items/Item" use="@WorkgroupCenter"/>
<xsl:key name="membership-by-workgroup" match="Membership/Items/Item" use="@WorkgroupID"/>
<xsl:key name="staff-by-id" match="Staff/Items/Item" use="@StaffID"/>
<xsl:template match="/dsQueryResponse">
<root>
<!-- for each distinct center -->
<xsl:for-each select="Staff/Items/Item[count(.|key('staff-by-center', @StaffCenter)[1]) = 1]">
<xsl:variable name="center" select="@StaffCenter" />
<!-- workgroups associated with the current center -->
<xsl:variable name="workgroups" select="key('workgroup-by-center', $center)" />
<!-- memberships associated with the workgroups -->
<xsl:variable name="memberships" select="key('membership-by-workgroup', $workgroups/@WorkgroupID)" />
<!-- distinct staff listed in memberships -->
<xsl:variable name="staff" select="key('staff-by-id', $memberships/@StaffID)" />
<center>
<name>
<xsl:value-of select="$center" />
</name>
<workgroups>
<xsl:copy-of select="$workgroups" />
</workgroups>
<memberships>
<xsl:copy-of select="$memberships" />
</memberships>
<all-staff>
<xsl:copy-of select="$staff" />
</all-staff>
<center-staff>
<xsl:copy-of select="$staff[@StaffCenter=$center]" />
</center-staff>
</center>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
Я использовал результат XML и скопировал соответствующие узлы вместо подсчета их, чтобы мы могли точно видеть, что делает каждый шаг.Применительно к вашему примеру ввода результат будет:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<center>
<name>Center1</name>
<workgroups>
<Item WorkgroupID="4001" WorkgroupCenter="Center1"/>
<Item WorkgroupID="4002" WorkgroupCenter="Center1"/>
</workgroups>
<memberships>
<Item StaffID="AJ1" WorkgroupID="4001"/>
<Item StaffID="AJ1" WorkgroupID="4001"/>
<Item StaffID="CG1" WorkgroupID="4001"/>
<Item StaffID="DH1" WorkgroupID="4002"/>
</memberships>
<all-staff>
<Item StaffName="Anne Jones" StaffCenter="Center1" StaffID="AJ1"/>
<Item StaffName="Charles Glover" StaffCenter="Center2" StaffID="CG1"/>
<Item StaffName="Donald Hill" StaffCenter="Center2" StaffID="DH1"/>
</all-staff>
<center-staff>
<Item StaffName="Anne Jones" StaffCenter="Center1" StaffID="AJ1"/>
</center-staff>
</center>
<center>
<name>Center2</name>
<workgroups>
<Item WorkgroupID="4003" WorkgroupCenter="Center2"/>
</workgroups>
<memberships>
<Item StaffID="AJ1" WorkgroupID="4003"/>
<Item StaffID="CG1" WorkgroupID="4003"/>
<Item StaffID="ED1" WorkgroupID="4003"/>
</memberships>
<all-staff>
<Item StaffName="Anne Jones" StaffCenter="Center1" StaffID="AJ1"/>
<Item StaffName="Charles Glover" StaffCenter="Center2" StaffID="CG1"/>
<Item StaffName="Evan Dolan" StaffCenter="Center3" StaffID="ED1"/>
</all-staff>
<center-staff>
<Item StaffName="Charles Glover" StaffCenter="Center2" StaffID="CG1"/>
</center-staff>
</center>
<center>
<name>Center3</name>
<workgroups/>
<memberships/>
<all-staff/>
<center-staff/>
</center>
</root>
Теперь, как вы можете видеть, эти результаты не соответствуют ожидаемому результату - например, ни одна группа узлов в Center2 не имеет счетчика 2Так что я либо группирую неправильные узлы, либо ваши ожидаемые значения отключены.Если первое, отредактируйте ваш вопрос и уточните логику, которую необходимо применить (как можно прийти к ожидаемому результату вручную).
Добавлено:
Во втором столбце указано количество уникальных членов каждого Центра (обозначается атрибутом "StaffCenter" в пунктах "Staff"), исключая любые элементы Staff.которые не имеют соответствующей записи в элементах «Членство» (StaffID).
Хорошо, тогда это должно быть относительно просто:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="staff-by-center" match="Staff/Items/Item" use="@StaffCenter"/>
<xsl:key name="memberhip-by-staff" match="Membership/Items/Item" use="@StaffID"/>
<xsl:template match="/dsQueryResponse">
<root>
<!-- for each distinct center -->
<xsl:for-each select="Staff/Items/Item[count(.|key('staff-by-center', @StaffCenter)[1]) = 1]">
<xsl:variable name="center" select="@StaffCenter" />
<!-- staff at current center -->
<xsl:variable name="all-staff" select="key('staff-by-center', $center)" />
<!-- exclude staff with no memberships -->
<xsl:variable name="staff" select="$all-staff[key('memberhip-by-staff', @StaffID)]" />
<center>
<name>
<xsl:value-of select="$center" />
</name>
<all-staff>
<xsl:copy-of select="$all-staff" />
</all-staff>
<staff>
<xsl:copy-of select="$staff" />
</staff>
</center>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
Результат
<?xml version="1.0" encoding="UTF-8"?>
<root>
<center>
<name>Center1</name>
<all-staff>
<Item StaffName="Anne Jones" StaffCenter="Center1" StaffID="AJ1"/>
<Item StaffName="Bill Smith" StaffCenter="Center1" StaffID="BS1"/>
</all-staff>
<staff>
<Item StaffName="Anne Jones" StaffCenter="Center1" StaffID="AJ1"/>
</staff>
</center>
<center>
<name>Center2</name>
<all-staff>
<Item StaffName="Charles Glover" StaffCenter="Center2" StaffID="CG1"/>
<Item StaffName="Donald Hill" StaffCenter="Center2" StaffID="DH1"/>
</all-staff>
<staff>
<Item StaffName="Charles Glover" StaffCenter="Center2" StaffID="CG1"/>
<Item StaffName="Donald Hill" StaffCenter="Center2" StaffID="DH1"/>
</staff>
</center>
<center>
<name>Center3</name>
<all-staff>
<Item StaffName="Evan Dolan" StaffCenter="Center3" StaffID="ED1"/>
<Item StaffName="Frank Miller" StaffCenter="Center3" StaffID="FM1"/>
</all-staff>
<staff>
<Item StaffName="Evan Dolan" StaffCenter="Center3" StaffID="ED1"/>
</staff>
</center>
</root>