How would I extract the unique SectionLabels for each FormDefin the following XML:
<XML>
<FormDef OID="F_TEST_1" Name="Test Form 1">
<ItemGroupRef ItemGroupOID="TEST_GROUP_1" />
<ItemGroupRef ItemGroupOID="TEST_GROUP_4" />
</FormDef>
<FormDef OID="F_TEST_2" Name="Test Form 2">
<ItemGroupRef ItemGroupOID="TEST_GROUP_2" />
</FormDef>
<FormDef OID="F_TEST_3" Name="Test Form 3">
<ItemGroupRef ItemGroupOID="TEST_GROUP_2"/>
<ItemGroupRef ItemGroupOID="TEST_GROUP_3"/>
</FormDef>
<FormDef OID="F_TEST_4" Name="Test Form 4">
<ItemGroupRef ItemGroupOID="TEST_GROUP_4"/>
</FormDef>
<ItemGroupDef OID="TEST_GROUP_1" Name="Ungrouped">
<ItemRef ItemOID="I_MSA1_INIT" />
<ItemRef ItemOID="I_MSA1_FORMD" />
<ItemRef ItemOID="I_MSA1_MSA1_CONS" />
<ItemRef ItemOID="I_MSA1_MSA1_PGT" />
</ItemGroupDef>
<ItemGroupDef OID="TEST_GROUP_2" Name="MSA1_complyreasG" >
<ItemRef ItemOID="I_MSA1_MSA1_NOELIGREAS" />
<ItemRef ItemOID="I_MSA1_MSA1_COMPLYREAS" />
</ItemGroupDef>
<ItemGroupDef OID="TEST_GROUP_3" Name="Ungrouped">
<ItemRef ItemOID="I_MSA2_INIT" />
<ItemRef ItemOID="I_MSA2_FROMD" />
<ItemRef ItemOID="I_MSA2_IDV" />
<ItemRef ItemOID="I_MSA2_MSA2_INITBF" />
</ItemGroupDef>
<ItemGroupDef OID="TEST_GROUP_4" Name="MSA2_POARTprecG">
<ItemRef ItemOID="I_MSA2_MSA2_POARTPREC" />
<ItemRef ItemOID="I_MSA2_MSA2_POARTNBV" />
<ItemRef ItemOID="I_MSA2_MSA2_LOARTPREC" />
</ItemGroupDef>
<ItemDef OID="I_MSA1_INIT">
<ItemDetails ItemOID="I_MSA1_INIT">
<ItemPresentInForm FormOID="F_TEST_1">
<SectionLabel>Section1</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA1_FORMD">
<ItemDetails ItemOID="I_MSA1_FORMD">
<ItemPresentInForm FormOID="F_TEST_1">
<SectionLabel>Section2</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA1_MSA1_CONS">
<ItemDetails ItemOID="I_MSA1_MSA1_CONS">
<ItemPresentInForm FormOID="F_TEST_1">
<SectionLabel>Section3</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA1_MSA1_NOELIGREAS">
<ItemDetails ItemOID="I_MSA1_MSA1_NOELIGREAS">
<ItemPresentInForm FormOID="F_TEST_2">
<SectionLabel>Section1</SectionLabel>
</ItemPresentInForm>
<ItemPresentInForm FormOID="F_TEST_3">
<SectionLabel>Section1</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA1_MSA1_COMPLYREAS">
<ItemDetails ItemOID="I_MSA1_MSA1_COMPLYREAS">
<ItemPresentInForm FormOID="F_TEST_2">
<SectionLabel>Section2</SectionLabel>
</ItemPresentInForm>
<ItemPresentInForm FormOID="F_TEST_3">
<SectionLabel>Section2</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA2_INIT">
<ItemDetails ItemOID="I_MSA2_INIT">
<ItemPresentInForm FormOID="F_TEST_3">
<SectionLabel>Section1</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA2_FROMD">
<ItemDetails ItemOID="I_MSA2_FROMD">
<ItemPresentInForm FormOID="F_TEST_3">
<SectionLabel>Section2</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA2_IDV">
<ItemDetails ItemOID="I_MSA2_IDV">
<ItemPresentInForm FormOID="F_TEST_3">
<SectionLabel>Section3</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA2_MSA2_POARTPREC">
<ItemDetails ItemOID="I_MSA2_MSA2_POARTPREC">
<ItemPresentInForm FormOID="F_TEST_1">
<SectionLabel>Section1</SectionLabel>
</ItemPresentInForm>
<ItemPresentInForm FormOID="F_TEST_4">
<SectionLabel>Section1</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA2_MSA2_POARTNBV">
<ItemDetails ItemOID="I_MSA2_MSA2_POARTNBV">
<ItemPresentInForm FormOID="F_TEST_1">
<SectionLabel>Section2</SectionLabel>
</ItemPresentInForm>
<ItemPresentInForm FormOID="F_TEST_4">
<SectionLabel>Section2</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
<ItemDef OID="I_MSA2_MSA2_LOARTPREC">
<ItemDetails ItemOID="I_MSA2_MSA2_LOARTPREC">
<ItemPresentInForm FormOID="F_TEST_1">
<SectionLabel>Section3</SectionLabel>
</ItemPresentInForm>
<ItemPresentInForm FormOID="F_TEST_4">
<SectionLabel>Section3</SectionLabel>
</ItemPresentInForm>
</ItemDetails>
</ItemDef>
</XML>
First I define a key:
<xsl:key name="labels" match="ItemDef/ItemDetails/ItemPresentInForm" use="@FormOID" />
Then use it in a select like so:
<xsl:variable name="sections"
select="//*[local-name()='ItemDef']/*[local-name()='ItemDetails']/*[local-name()='ItemPresentInForm']
[generate-id() = generate-id(key('labels', @FormOID))]">
<xsl:value-of select="./SectionLabel" />
</xsl:variable>
But this returns:
Section1
Section1
Section1
Section1
Changing the key to pitch on the SectionLabel:
<xsl:key name="labels" match="ItemDef/ItemDetails/ItemPresentInForm" use="SectionLabel" />
XSLT to transform:
<xsl:variable name="sections"
select="//*[local-name()='ItemDef']/*[local-name()='ItemDetails']/*[local-name()='ItemPresentInForm']
[generate-id(.) = generate-id(key('labels', SectionLabel))]">
<xsl:value-of select="./SectionLabel" />
</xsl:variable>
Returns this:
Section1
Section2
Section3
Section4
Section1
Section2
Section3
Section4
Section1
Section2
Section3
Section4
Section1
Section2
Section3
Section4
Which is all the section labels in the document when I am iterating over each FormDef. I am aiming to get an output where only the section labels for the current FormDef are extracted.
The expected output should be:
Form OID="F_TEST_1"
Labels: Section1, Section2, Section3
Form OID="F_TEST_2"
Labels: Section1, Section2
Form OID="F_TEST_3"
Labels: Section1, Section2, Section3
Form OID="F_TEST_4"
Labels: Section1, Section2, Section3
Thanks
This transformation:
when applied on the provided XML document:
produces the wanted, correct result (the unique
SectionLabelvalues for each form):Explanation:
Muenchian grouping method where the elements to be grouped are indexed using a composite key.
Each unique section value in a form is identified by the concatenation of the
SectionLabelstring value and the string value of theFormOIDattribute of its parent.In this way the same
SectionLabelvalue in different forms produces different keys and isn’t counted just once.Here are some good resources on Muenchian grouping:
Jeni Tennison’s grouping page.
Dave Pawson's XSLT FAQ's grouping page.