How to use only distinct values within XSLT for-each loop - xslt

I am trying to retrieve only distinct values of an element. This is my XML:
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cF">
<property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
<property key="MeterClassTypeCode" value="cF"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cE">
<property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
<property key="MeterClassTypeCode" value="cE"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cC">
<property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
<property key="MeterClassTypeCode" value="cC"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cD">
<property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
<property key="MeterClassTypeCode" value="cD"/>
</LaunchedMeterClass>
I want to create an XPath to get only those "LaunchedMeterClass" nodes having an unique value for <property key="ClusterContractUUID">. At the moment, I am using the following:
<xsl:for-each select="./descendant::LaunchedMeterClass">
<xsl:choose>
<xsl:when test="./property/#key='ClusterContractUUID'">
<contract-type>
<property>
<xsl:attribute name="key">ClusterContractUUID</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="./property[#key='ClusterContractUUID']/#value"/>
</xsl:attribute>
</property>
</contract-type>
</xsl:when>
<xsl:otherwise>
<contract-type>
<property>
<xsl:attribute name="key">contractTypeCategory</xsl:attribute>
</property>
</contract-type>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
But this gives me all the elements including duplicates:
<contract-type>
<property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
</contract-type>
<contract-type>
<property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
</contract-type>
<contract-type>
<property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
</contract-type>
<contract-type>
<property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
</contract-type>
How can I write an XPath which gives only distinct values? My desired output is:
<contract-type>
<property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
</contract-type>
<contract-type>
<property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
</contract-type>
Thank you in advance for your help!

Try this:
XML:
<root>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cF">
<property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
<property key="MeterClassTypeCode" value="cF"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cE">
<property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
<property key="MeterClassTypeCode" value="cE"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cC">
<property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
<property key="MeterClassTypeCode" value="cC"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cD">
<property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
<property key="MeterClassTypeCode" value="cD"/>
</LaunchedMeterClass>
</root>
XSLT2.0
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="root">
<xsl:for-each select="distinct-values(descendant::property[#key='ClusterContractUUID']/#value)">
<contract-type>
<property>
<xsl:attribute name="key">ClusterContractUUID</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="."/>
</xsl:attribute>
</property>
</contract-type>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Result:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<contract-type>
<property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
</contract-type>
<contract-type>
<property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
</contract-type>
</root>
Edit:
Edited to get following-sibling values. In above XSLT, template match is # attributes side, instead of that if template match at elements, we can access the other siblings, ancestors, descendants, etc, easily.
XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy><xsl:apply-templates select="#* | node()"/></xsl:copy>
</xsl:template>
<xsl:template match="root">
<root>
<xsl:for-each select="descendant::property[#key='ClusterContractUUID'
and not(#value=preceding::property[#key='ClusterContractUUID']/#value)]">
<contract-type>
<xsl:copy><xsl:apply-templates select="#*|node()"/></xsl:copy>
<xsl:apply-templates select="following-sibling::property"/>
</contract-type>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>

You can perhaps try exslt's set:distinct:
http://exslt.org/set/functions/distinct/
There's an example at the bottom. Your mileage may vary.

This is generally known as "grouping".
In XSLT 2.0, use the <xsl:for-each-group> construct.
In XSLT 1.0, use "Muenchian grouping" - you'll find that in your favourite XSLT textbook, or in online resources.
If you really need to do it in XPath rather than XSLT (your question is unclear) the best you can do is the XPath 2.0 distinct-values() function - there's nothing in XPath 1.0 that will help you much.

Related

How to use XSLT to generate one ouput xml file by reading & processing from multiple input xml

Friends,
I am new to XSLT. Please help to get the below logic. I am using unix machine
From the below 3 input xml file, need to add 'count' field value by using xslt and need to generate output with added value in count field
Input XML 1
<topic>
<topicName>Billing</topicName>
<property>
<make>HONDA</make>
<Model>ACCORD</Model>
</property>
<count>10</count>
</topic>
<topic>
<topicName>Billing</topicName>
<property>
<make>TOYOTO</make>
<Model>CAMRY</Model>
</property>
<count>20</count>
</topic>
<topic>
<topicName>Billing</topicName>
<property>
<make>NISSAN</make>
<Model>ALTIMA</Model>
</property>
<count>30</count>
</topic>
Input XML 2
<topic>
<topicName>Billing</topicName>
<property>
<make>HONDA</make>
<Model>ACCORD</Model>
</property>
<count>100</count>
</topic>
<topic>
<topicName>Billing</topicName>
<property>
<make>TOYOTO</make>
<Model>CAMRY</Model>
</property>
<count>200</count>
</topic>
<topic>
<topicName>Billing</topicName>
<property>
<make>NISSAN</make>
<Model>ALTIMA</Model>
</property>
<count>300</count>
</topic>
Input XML 3
<topic>
<topicName>Billing</topicName>
<property>
<make>HONDA</make>
<Model>ACCORD</Model>
</property>
<count>1000</count>
</topic>
<topic>
<topicName>Billing</topicName>
<property>
<make>TOYOTO</make>
<Model>CAMRY</Model>
</property>
<count>2000</count>
</topic>
<topic>
<topicName>Billing</topicName>
<property>
<make>NISSAN</make>
<Model>ALTIMA</Model>
</property>
<count>3000</count>
</topic>
From the above 3 input xml file, need to add count value by using xslt and need to generate output with added value for count field
OUTPUT XML:
<topic>
<topicName>Billing</topicName>
<property>
<make>HONDA</make>
<Model>ACCORD</Model>
</property>
<count>1110</count>
</topic>
<topic>
<topicName>Billing</topicName>
<property>
<make>TOYOTO</make>
<Model>CAMRY</Model>
</property>
<count>2220</count>
</topic>
<topic>
<topicName>Billing</topicName>
<property>
<make>NISSAN</make>
<Model>ALTIMA</Model>
</property>
<count>3330</count>
</topic>
Thanks in Advance
Read up on the document() function, and (for 1.1) the doc() function.
In 1.1, read up on xsl:for-each-group and deep-equal().
In both 1.0 and 1.1, read up on sum().
You can read in files using collection (the syntax used in the sample is Saxon 9 specific):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:param name="file-pattern" select="'topic*.xml'"/>
<xsl:template name="main">
<xsl:for-each-group select="collection(concat('.?select=', $file-pattern))//topic" group-by="concat(property/make, '|', property/Model)">
<xsl:copy>
<xsl:copy-of select="topicName, property"/>
<count>
<xsl:value-of select="sum(current-group()/count)"/>
</count>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Run Saxon 9 using -it:main to start with that template called main.

XSLT finding distinct combinations

I am beginner to xslt. I want to find all unique combinations for Year, Month, Day, and Hour.
I have following xml file to transform:
<Plans>
<Plan Name="Plan_1">
<Book Name="Book_1">
<Time Name="AAA">
<Property Name="Year" Value="2001"/>
<Property Name="Month" Value="01"/>
<Property Name="Day" Value="10"/>
<Property Name="Hour" Value="12"/>
</Time>
<Time Name="BBB">
<Property Name="Year" Value="2001"/>
<Property Name="Month" Value="01"/>
<Property Name="Day" Value="10"/>
<Property Name="Hour" Value="12"/>
</Time>
<Time Name="CCC">
<Property Name="Year" Value="2004"/>
<Property Name="Month" Value="02"/>
<Property Name="Day" Value="11"/>
<Property Name="Hour" Value="04"/>
</Time>
<Time Name="DDD">
<Property Name="Year" Value="2004"/>
<Property Name="Month" Value="03"/>
<Property Name="Day" Value="20"/>
<Property Name="Hour" Value="04"/>
</Time>
</Book>
<Book Name="Book_22">
<Time Name="CCC">
<Property Name="Year" Value="2001"/>
<Property Name="Month" Value="01"/>
<Property Name="Day" Value="10"/>
<Property Name="Hour" Value="12"/>
</Time>
<Time Name="DDD">
<Property Name="Year" Value="2002"/>
<Property Name="Month" Value="03"/>
<Property Name="Day" Value="23"/>
<Property Name="Hour" Value="03"/>
</Time>
<Time Name="EEE">
<Property Name="Year" Value="2002"/>
<Property Name="Month" Value="03"/>
<Property Name="Day" Value="23"/>
<Property Name="Hour" Value="03"/>
</Time>
<Time Name="FFF">
<Property Name="Year" Value="2004"/>
<Property Name="Month" Value="02"/>
<Property Name="Day" Value="11"/>
<Property Name="Hour" Value="04"/>
</Time>
</Book>
</Plan>
</Plans>
Input xml has total eight total combinations (Four from each book).
I just want to know distinct combinations. So output should have 6 combinations because there are two same combinations. The name of books does not matter. I just want to see how many combinations there are. And just label from 1 to the number... It does not have to be in any order although it can be ordered by time... If it is too hard to label numbers, then I just need to get distinct combinations only...
<Times>
<Time Value="1">
<Property Name="Year" Value="2001"/>
<Property Name="Month" Value="01"/>
<Property Name="Day" Value="10"/>
<Property Name="Hour" Value="12"/>
</Time>
<Time Value="2">
<Property Name="Year" Value="2004"/>
<Property Name="Month" Value="02"/>
<Property Name="Day" Value="11"/>
<Property Name="Hour" Value="04"/>
</Time>
<Time Value="3">
<Property Name="Year" Value="2004"/>
<Property Name="Month" Value="03"/>
<Property Name="Day" Value="20"/>
<Property Name="Hour" Value="04"/>
</Time>
<Time Value="4">
<Property Name="Year" Value="2001"/>
<Property Name="Month" Value="01"/>
<Property Name="Day" Value="10"/>
<Property Name="Hour" Value="12"/>
</Time>
<Time Value="5">
<Property Name="Year" Value="2002"/>
<Property Name="Month" Value="03"/>
<Property Name="Day" Value="23"/>
<Property Name="Hour" Value="03"/>
</Time>
</Times>
I tried to read for-each-group. But I cannot make it work... Does it have to be four loops or something since there are four porperties? Please help me...
Similar to the other answers, you could also make use of xsl:for-each-group here.
<xsl:for-each-group select=".//Time" group-by="string-join(Property/#Value, '|')">
If your XSLT was using the Identity Template, you could then output the distinct Time elements within this group simply by doing this
<Time Value="{position()}">
<xsl:apply-templates />
</Time>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/*">
<Times>
<xsl:for-each-group select=".//Time" group-by="string-join(Property/#Value, '|')">
<Time Value="{position()}">
<xsl:apply-templates />
</Time>
</xsl:for-each-group>
</Times>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Now, you mention in comments (but not in the question) about having multiple Plan elements, but you have not said if you want to select distinct Time elements across all Plan elements, or have distinct elements for each separate Plan.
Suppose you did want to show distinct Time elements for each separate Plan, then just a small tweak will do. You would just effectively match the Plan element and have the grouping in that
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="Plan">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:for-each-group select=".//Time" group-by="string-join(Property/#Value, '|')">
<Time Value="{position()}">
<xsl:apply-templates />
</Time>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Do note these assume the order of your Property elements will always be the same ("Year", "Month", "Day", "Hour"). If not, you can get around this by doing the following
<xsl:for-each-group select=".//Time" group-by="concat(
Property[#Name='Year']/#Value, '|',
Property[#Name='Month']/#Value, '|',
Property[#Name='Day']/#Value, '|',
Property[#Name='Hour']/#Value, '|')">
Use
distinct-values(/Times/Time/string-join(Property/#Value, '|'))
to get the distinct values. Then if necessary split them up into their component fields using tokenize().
The following stylesheet builds upon the answer given by #Michael Kay. This is just to illustrate the solution and prove that it is working. Please accept his answer!
Numbering output elements is not hard, the easiest way is using position() in an attribute value template.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/Plans">
<Times>
<xsl:for-each select="distinct-values(//Time/string-join(Property/#Value, '|'))">
<xsl:variable name="tokens" select="tokenize(.,'\|')"/>
<Time Value="{position()}">
<Property Name="Year" Value="{$tokens[1]}"/>
<Property Name="Month" Value="{$tokens[2]}"/>
<Property Name="Day" Value="{$tokens[3]}"/>
<Property Name="Hour" Value="{$tokens[4]}"/>
</Time>
</xsl:for-each>
</Times>
</xsl:template>
</xsl:stylesheet>
Output
As mentioned by #Tim C, you are probably expecting 4 result elements.
<?xml version="1.0" encoding="UTF-8"?>
<Times>
<Time Value="1">
<Property Name="Year" Value="2001"/>
<Property Name="Month" Value="01"/>
<Property Name="Day" Value="10"/>
<Property Name="Hour" Value="12"/>
</Time>
<Time Value="2">
<Property Name="Year" Value="2004"/>
<Property Name="Month" Value="02"/>
<Property Name="Day" Value="11"/>
<Property Name="Hour" Value="04"/>
</Time>
<Time Value="3">
<Property Name="Year" Value="2004"/>
<Property Name="Month" Value="03"/>
<Property Name="Day" Value="20"/>
<Property Name="Hour" Value="04"/>
</Time>
<Time Value="4">
<Property Name="Year" Value="2002"/>
<Property Name="Month" Value="03"/>
<Property Name="Day" Value="23"/>
<Property Name="Hour" Value="03"/>
</Time>
</Times>

XSLT output value-of select is incorrect

My template_1.xml file
<?xml version="1.0" encoding="UTF-8"?>
<DSExport>
<TableDefinitions>
<Property Name="Category">\Table Definitions\Teradata\XML_TEST</Property>
<Property Name="ShortDesc">Imported from: SRC_COLUMN_ADD_TEST</Property>
<Collection Name="Columns" Type="MetaColumn">
<SubRecord>
<Property Name="Name">CUST_ID_1</Property>
<Property Name="Description">CUST_ID: nullable int32</Property>
<Property Name="SqlType">4</Property>
<Property Name="Precision">9</Property>
<Property Name="Scale">0</Property>
<Property Name="Nullable">1</Property>
</SubRecord>
<SubRecord>
<Property Name="Name">DESCR</Property>
<Property Name="Description">DESCR: nullable string[max=144]</Property>
<Property Name="SqlType">12</Property>
<Property Name="Precision">144</Property>
<Property Name="Scale">0</Property>
<Property Name="Nullable">1</Property>
</SubRecord>
<SubRecord>
<Property Name="Name">CUST_ADDR</Property>
<Property Name="Description">CUST_ADDR: string[max=500]</Property>
<Property Name="SqlType">12</Property>
<Property Name="Precision">500</Property>
<Property Name="Scale">0</Property>
<Property Name="Nullable">0</Property>
</SubRecord>
<SubRecord>
<Property Name="Name">AGE</Property>
<Property Name="Description">AGE: nullable int32</Property>
<Property Name="SqlType">4</Property>
<Property Name="Precision">9</Property>
<Property Name="Scale">0</Property>
<Property Name="Nullable">1</Property>
</SubRecord>
</Collection>
Hi I am new to XSLT , I tried lot to get my expected out as mentioned below, some how am getting result only from same attribute value of same element, please help on this...Thanks
My template.xsl file
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<DSExport>
<id-of>
<xsl:for-each select="//SubRecord">
<SubRecord>
<xsl:value-of select="//SubRecord/Property[#Name]" />
</SubRecord>
</xsl:for-each>
</id-of>
</DSExport>
</xsl:template>
</xsl:stylesheet>
My current ouput: output.xml
<?xml version="1.0" encoding="UTF-8"?>
<DSExport>
<id-of>
<SubRecord>CUST_ID_1</SubRecord>
<SubRecord>CUST_ID_1</SubRecord>
<SubRecord>CUST_ID_1</SubRecord>
<SubRecord>CUST_ID_1</SubRecord>
</id-of>
</DSExport>
My expected output :
<?xml version="1.0" encoding="UTF-8"?>
<DSExport>
<id-of>
<SubRecord>CUST_ID_1</SubRecord>
<SubRecord>DESCR</SubRecord>
<SubRecord>CUST_ADDR</SubRecord>
<SubRecord>AGE</SubRecord>
</id-of>
</DSExport>
Your problem is with this expression
<xsl:value-of select="//SubRecord/Property[#Name]" />
The first slash at the start of the xpath expression indicates it is an absolute path, and so it will start searching from the document element. Two slashes then indicate it will search for the SubRecord element at any level in the document. This results in it always finding the first SubRecord element in the XML, regardless of where you are currently positioned.
You need to use a relative expression here. It will be relative to the context node you are currently positioned on (which is a SubRecord element). Try replacing it with this
<xsl:value-of select="Property[#Name]" />
Note that, strictly speaking this will get the first Property element which has an attribute of Name present. Although this gives your expected result, maybe it would be better written as this
<xsl:value-of select="Property[#Name='Name']" />
i.e. Get the Property which has a Name attribute with a value of Name.

access the value of attribute (as a variable)

I'm trying to transform my xml file:
<root>
<group id="F_123" >
<term id="F_123_d" >
<word>blabla</word>
<instruction>blabla</instruction>
</term>
<term id="F_123">
<word>blabla</word>
<instruction>blabla</instruction>
<numbers>
<number code="01" >1</number>
<number code="02" >2</number>
<number code="03" >3</number>
<number code="04" >4</number>
<number code="05" >5</number>
</numbers>
</term>
<term id="F_124">
<word>blabla</word>
<numbers>
<number code="01" >1</number>
<number code="02" >2</number>
<number code="03" >3</number>
<number code="04" >4</number>
<number code="05" >5</number>
</numbers>
</term>
<term id="F_125">
<word>blabla</word>
<numbers>
<number code="01" >1</number>
<number code="02" >2</number>
<number code="03" >3</number>
<number code="04" >4</number>
<number code="05" >5</number>
</numbers>
</term>
<routing id="F_123_1">
<condition>
<operator type="or">
<operator type="or">
<operator type="equal">
<variable name="F_D01a3DE1"/>
<constant>DK</constant>
</operator>
<operator type="equal">
<variable name="F_D01a3DE1"/>
<constant>RF</constant>
</operator>
</operator>
<operator type="equal">
<variable name="F_D01a3DE1"/>
<constant>1</constant>
</operator>
</operator>
</condition>
<then>
<goto group="A_24"/>
</then>
<else>
<routing>
<condition>
<operator type="or">
<operator type="or">
<operator type="equal">
<variable name="B_D01a3DE1"/>
<constant>5</constant>
</operator>
<operator type="equal">
<variable name="B_D01a3DE1"/>
<constant>10</constant>
</operator>
</operator>
<operator type="equal">
<variable name="B_D01a3DE1"/>
<constant>7</constant>
</operator>
</operator>
</condition>
<then>
<goto group="A_25"/>
</then>
<else>
<routing>
<condition>
<operator type="or">
<operator type="equal">
<variable name="B_D01a3DE1"/>
<constant>6</constant>
</operator>
<operator type="equal">
<variable name="B_D01a3DE1"/>
<constant>11</constant>
</operator>
</operator>
</condition>
<then>
<goto group="A_26"/>
</then>
<else>
<goto group="A_27"/>
</else>
</routing>
</else>
</routing>
</else>
</routing>
</group>
<group id="A_25" >
<term id="A_25" >
<word>blabla</word>
<instruction>blabla</instruction>
</term>
<term id="A_26">
<word>blabla</word>
<instruction>blabla</instruction>
<numbers>
<number code="01" >1</number>
<number code="02" >2</number>
</numbers>
</term>
</group>
</root>
I want to access the value of #group/term/#id and make one element per each term in <group id="A_25">. Is it possible?
It's not very clear what exactly do you want, so a guess follows:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="group/term/#id">
<id>
<xsl:value-of select="."/>
</id>
</xsl:template>
<xsl:template match="/">
<root>
<xsl:apply-templates select="node()" />
</root>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:apply-templates select="node()|#*" />
</xsl:template>
</xsl:stylesheet>
When applied to your example (I had to add a root element to it, so that it's valid), it produces:
<root>
<id>F_123_d</id>
<id>F_123</id>
<id>F_124</id>
<id>F_125</id>
<id>A_25</id>
<id>A_26</id>
</root>
I want to access the value of
#group/term/#id and make one element
per each term in <group id="A_25">. Is
it possible?
This XPath expression select what I think you want:
/root/group[#id='A_25']/term/#id
Also, this stylesheet process what I think you want:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="text()"/>
<xsl:template match="group[#id='A_25']/term">
<element id="{#id}"/>
</xsl:template>
</xsl:stylesheet>
Output:
<element id="A_25" />
<element id="A_26" />

Counting nodes with certain attribute values in XSLT

Suppose I have some XML like this:
<section name="SampleSection">
<item name="ScoredItem1">
<attributes>
<scored data_type="boolean" value="true"/>
</attributes>
</item>
<item name="UnscoredItem1">
<attributes>
<scored data_type="boolean" value="false"/>
</attributes>
</item>
<item key="(3272fbb5:22)" name="ScoredItem2">
<attributes>
<scored data_type="boolean" value="true"/>
</attributes>
</item>
</section>
Now, I know, using XSLT, I can count the items that have a scored attribute like this:
<xsl:variable name="scoredItems" select="item/attributes/scored"/>
<xsl:value-of select="count($scoredItems)"/>
This will give me a value of 3, of course.
Suppose I only want to count those items for which scored is true. How do I do that using XSLT? (This should return a value of 2 for this example.
Do it like this:
<xsl:variable name="scoredItems"
select=
"item/attributes/scored[#value='true']"/>