access the value of attribute (as a variable) - xslt

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" />

Related

FFPlay: How to manually select video quality during playing the mpd stream?

I used ffplay to play mpd stream and successed,
Here the MPD file:
<?xml version="1.0" encoding="utf-8"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
profiles="urn:mpeg:dash:profile:isoff-live:2011"
type="static"
mediaPresentationDuration="PT1M8.7S"
maxSegmentDuration="PT5.0S"
minBufferTime="PT12.5S">
<ProgramInformation>
</ProgramInformation>
<ServiceDescription id="0">
</ServiceDescription>
<Period id="0" start="PT0.0S">
<AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="24000/1001" maxWidth="1280" maxHeight="720" par="16:9">
<Representation id="0" mimeType="video/mp4" codecs="avc1.4d401f" bandwidth="10237" width="480" height="270" sar="1:1">
<SegmentTemplate timescale="24000" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
<SegmentTimeline>
<S t="0" d="150150" r="9" />
<S d="149149" />
</SegmentTimeline>
</SegmentTemplate>
</Representation>
<Representation id="2" mimeType="video/mp4" codecs="avc1.4d401f" bandwidth="60882" width="1280" height="720" sar="1:1">
<SegmentTemplate timescale="24000" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
<SegmentTimeline>
<S t="0" d="150150" r="9" />
<S d="149149" />
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" lang="und">
<Representation id="1" mimeType="audio/mp4" codecs="mp4a.40.2" bandwidth="128000" audioSamplingRate="32000">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
<SegmentTemplate timescale="32000" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
<SegmentTimeline>
<S t="0" d="159744" />
<S d="160768" r="11" />
<S d="111915" />
</SegmentTimeline>
</SegmentTemplate>
</Representation>
<Representation id="3" mimeType="audio/mp4" codecs="mp4a.40.2" bandwidth="128000" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
<SegmentTemplate timescale="44100" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
<SegmentTimeline>
<S t="0" d="220160" />
<S d="221184" r="11" />
<S d="158713" />
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
this dash stream contains 2 vindeos(480P and 720P), and 2 audios.The videos always starts low quality(480P), I want to change the video resolution to the high quality(720P) during playing process, what should i do?

XSLT: mix nodes if they have same id

i have xml with similar structure:
<Info>
<parents>
<parent1>
<id>1</id>
</parent1>
<parent2>
<id>2</id>
</parent2>
</parents>
<children>
<child>
<id>1</id>
<parentID>
1
</parentID>
<someInfoFromOneNode>
qqq
</someInfoFromOneNode>
</child>
<child>
<id>1</id>
<parentID>
1
</parentID>
<someInfoFromAnOtherNode>
qqq
</someInfoFromAnOtherNode>
</child>
<child>
<id>2</id>
<parentID>
2
</parentID>
<someInfoFromOneNode>
qqq
</someInfoFromOneNode>
</child>
<child>
<id>2</id>
<parentID>
2
</parentID>
<someInfoFromAnOtherNode>
qqq
</someInfoFromAnOtherNode>
</child>
</children>
</Info>
i need to get xml with that structure:
<Info>
<parent>
<id>1</id>
<children>
<chidl>
<id>1</id>
<someInfoFromOneNode>
qqq
</someInfoFromOneNode>
<someInfoFromAnOtherNode>
qqq
</someInfoFromAnOtherNode>
</chidl>
</children>
</parent>
<parent>
<id>2</id>
<children>
<chidl>
<id>2</id>
<someInfoFromOneNode>
qqq
</someInfoFromOneNode>
<someInfoFromAnOtherNode>
qqq
</someInfoFromAnOtherNode>
</chidl>
</children>
</parent>
</Info>
So i need to collect all children of one parent and in addition collect info related to one child. I've tried to filter children like this and displayed at least children ids(i keep the parentId):
<children>
<xsl:for-each select="/Info/children/child">
<xsl:if test="./price_groups_id = $parentId and not(./id = preceding-sibling::id)">
<child>
<id>
<xsl:value-of select="./id"/>
</id
</child>
</xsl:if>
</xsl:for-each>
</children>
But it only filters children by parent id and duplicate them, so current result is that:
<Info>
<parent>
<id>1</id>
<children>
<child>
<id>1</id>
</child>
<child>
<id>1</id>
</child>
</children>
</parent>
<parent>
<id>2</id>
<children>
<child>
<id>2</id>
</child>
<child>
<id>2</id>
</child>
</children>
</parent>
</Info>
What can i do to check previous node id and filter by it?

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

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.

Apache Camel: set body with regex pattern in Spring DCL

I try to set String body, having cut from it the piece, with the the regular expression, as follows:
<setBody>
<simple>${body} regex '?(:.xml xsi:type="xsd:string">(.*[\s\S]*?)..xml>)'</simple>
</setBody>
it is compiled normally but started with an error:
org.apache.cxf.interceptor.Fault: javax.xml.transform.TransformerException: com.sun.org.apache.xml.internal.utils.WrappedRuntimeException: Illegal processing instruction target ("xml"); xml (case insensitive) is reserved by the specs.
at [row,col {unknown-source}]: [6,7]
also I rty to do this with
<transform> ... </transform>
and the same error appears while running.
Please provide me the simple way to transform the body String in spring DSL by cutting it.
I want to cut xml data from soap plain request:
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:SMSServiceControllerwsdl">
<soapenv:Header/>
<soapenv:Body>
<urn:sendMessages soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<xml xsi:type="xsd:string">
<?xml version="1.0" encoding="UTF-8"?>
<Structure>
<Array name="messageArray">
<Structure>
<Value name="id">
<Type>String</Type>
<Data>ИД СООБЩЕНИЯ 1</Data>
</Value>
<Value name="phone">
<Type>String</Type>
<Data>ТЕЛЕФОН 1</Data>
</Value>
<Value name="text">
<Type>String</Type>
<Data>ТЕКСТ 1</Data>
</Value>
</Structure>
<Structure>
<Value name="id">
<Type>String</Type>
<Data>ИД СООБЩЕНИЯ 2</Data>
</Value>
<Value name="phone">
<Type>String</Type>
<Data>ТЕЛЕФОН 2</Data>
</Value>
<Value name="text">
<Type>String</Type>
<Data>ТЕКСТ 2</Data>
</Value>
</Structure>
</Array>
</Structure>
</xml>
<systemName xsi:type="xsd:string">awis</systemName>
</urn:sendMessages>
</soapenv:Body>
</soapenv:Envelope>
Use a splitter with an XPath expression such as:
<split>
<xpath>//Structure/Array/Structure</xpath>
<log message="split: ${body}"/>
</split>

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>