Grouping list of dates by year, using XSLT 1.0 - xslt-1.0

Could you help me? I have XML:
<root>
<prop>
<holidays>2011-01-01</holidays>
<holidays>2011-01-02</holidays>
...
<holidays>2012-01-01</holidays>
<holidays>2012-01-02</holidays>
...
</prop>
</root>
I need to get the following JSON from it:
[
{
"id" : "2011",
"data" :
[
"2011-01-01","2011-01-02" ...
]
},
{
"id" : "2012",
"data" :
[
"2012-01-01","2012-01-02" ...
]
},
...
]
With XSLT transformation 1.0
Thank you in Advance for your help!
UPDATE: Here is a solution that suited me
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="text"/>
<xsl:key name="group" match="prop/holidays" use="substring-before(string(.),'-')"/>
<xsl:template match="root">[
<xsl:apply-templates select="prop/holidays[generate-id(.) = generate-id(key('group',substring-before(string(.),'-')))]" />]</xsl:template>
<xsl:template match="holidays">{
"id" : "<xsl:value-of select="substring-before(string(.),'-')"/>",
"data" :
[
<xsl:for-each select="key('group',substring-before(string(.),'-'))">"<xsl:value-of select="."/>",</xsl:for-each>
]
},
</xsl:template>
</xsl:stylesheet>

Related

XSL - Check if select has no text nodes then show "Not Results"

How can I check if my block/select has no text nodes then show "Not Results"
<xsl:choose>
<xsl:when test="#pass='0' or #pass='1'">
<fo:block padding-top="1cm" font-weight="bold" margin-bottom="0.2cm">Header</fo:block> <fo:block margin-top="0.2cm" margin-bottom="0.2cm" border-bottom="1px solid #e1e1e1">
</fo:block>
<fo:block margin-top="0.2cm" margin-bottom="0.2cm" padding-left="5px" padding-right="5px" padding-top="1px">
<xsl:apply-templates select="detail/katalog/frage[#ko='1' and #passed='0']" />
<xsl:apply-templates select="detail/katalog/frage/options" />
<xsl:apply-templates select="detail/katalog/matrix/frage/options" />
<xsl:apply-templates select="detail/katalog/clusterArea/clusterFrage[#ko='1' and #passed='0']" />
</fo:block>
I tried this, but it doesn't work.
<xsl:if test="(not(detail/katalog/frage[#ko='1' and #passed='0']) and not(detail/katalog/clusterArea/clusterFrage[#ko='1' and #passed='0']) and not(detail/katalog/frage/options) and not(detail/katalog/matrix/frage/options))">
<fo:block>
Not Results
</fo:block>
</xsl:if>
Thanks a lot!
PR
If the elements you are checking exist, but your current check detail/katalog/frage[#ko='1' and #passed='0'] for example will return true, as that is just checking for the existence of the element itself, regardless of whether it has child nodes or not
So, you want to do something like this....
not(detail/katalog/frage[#ko='1' and #passed='0']/text())
However, you also need to watch out for whitespace only nodes, so you might want to augment the check like so...
not(detail/katalog/frage[#ko='1' and #passed='0']/text()[normalize-space()])
Alternatively, you could strip out whitespace only nodes by using xsl:strip-space
<xsl:strip-space elements="*" />

Mule Dataweave script for retrieving attributes in Xml

My Input Xml looks like below
<?xml version="1.0" encoding="UTF-8"?>
<elements>
<element>
<id>123</id>
<items>
<item>
<attributes>
<attribute attribute-id="test1">attr1</attribute>
<attribute attribute-id="test2">attr2</attribute>
</attributes>
</item>
</items>
</element>
</elements>
I tried with below Dataweave script:
%dw 1.0
%output application/xml
---
{
elements: { (payload.elements.*element map {
element: {
test1 : $.items.item.attributes.attribute when $.items.item.attributes.attribute.#attribute-id == 'test1' otherwise '',
test2 : $.items.item.attributes.attribute when $.items.item.attributes.attribute.#attribute-id == 'test2' otherwise ''
}
}
)
}
}
Expected output:
<?xml version='1.0' encoding='windows-1252'?>
<elements>
<element>
<test1>attr1</test1>
<test2>attr2</test2>
</element>
</elements>
Actual output:
<?xml version='1.0' encoding='windows-1252'?>
<elements>
<element>
<test1>attr1</test1>
<test2></test2>
</element>
</elements>
What changes are needed in my data weave script to get the expected output?
Try this
%dw 1.0
%output application/xml
---
{
elements: { (payload.elements.*element map {
element: {($.items.item.attributes.*attribute map {
($.#attribute-id) : $
})}
}
)
}
Yours is not working as there are multiple items.item.attributes.attribute
Hope this helps.
Check the below script
%dw 1.0
%output application/xml
---
{
elements: {
(payload.elements.*element map {
element: {
($.items.item.attributes.*attribute map ((element, index) -> {
(element.#attribute-id) : element when element.#attribute-id == "test1" or element.#attribute-id == "test2"
otherwise ''
}))
}
}
)
}
}
It checks the attribute-id for "test1 and test2", if different sets the value as empty.

XSL - Sum of computed amounts with comparison

I need some help to compute sum and add some comparison complexity to know which element should be part of the sum.
Let's take the following XML
<REF>
<amount>3</amount>
<rate>7</rate>
</REF>
<A>
<amount>10</amount>
<rate>4</rate>
</A>
<A>
<amount>-21</amount>
<rate>2</rate>
</A>
<B>
<amount>8</amount>
<rate>1</rate>
</B>
<C>
<amount>7</amount>
<rate>32</rate>
</C>
I would like to display the sum of each amount multiplied by each associated rate within a Total element.
And I would like to split my total into two elements: NegativeTotal and PositiveTotal.
PostiveTotal will contain the SUM of ((amount * rate) if the value is greater than (amount * rate) of REF object)
NegativeTotal will contain the SUM of ((amount * rate) if the value is less than (amount * rate) of REF object)
It should give the below output
<Total>
<PositiveTotal>
264 <!-- 40 + 224 -->
</PositiveTotal>
<NegativeTotal>
-34 <!-- -42 + 8 -->
</NegativeTotal>
</Total>
Please let me know if it's possible
For information technical limitation: XSLT 1.0
Thanks in advance
Regards,
I would suggest you do it this way:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<!-- first pass -->
<xsl:variable name="summands-rtf">
<xsl:for-each select="*">
<value>
<xsl:value-of select="amount * rate" />
</value>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="summands" select="exsl:node-set($summands-rtf)/value" />
<!-- get the threshold -->
<xsl:variable name="threshold" select="REF/amount * REF/rate" />
<!-- output -->
<Total>
<PositiveTotal>
<xsl:value-of select="sum($summands[. > $threshold])" />
</PositiveTotal>
<NegativeTotal>
<xsl:value-of select="sum($summands[. < $threshold])" />
</NegativeTotal>
</Total>
</xsl:template>
</xsl:stylesheet>
When applied to a well-formed XML input (with a single root element):
XML
<root>
<REF>
<amount>3</amount>
<rate>7</rate>
</REF>
<A>
<amount>10</amount>
<rate>4</rate>
</A>
<A>
<amount>-21</amount>
<rate>2</rate>
</A>
<B>
<amount>8</amount>
<rate>1</rate>
</B>
<C>
<amount>7</amount>
<rate>32</rate>
</C>
</root>
the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<Total>
<PositiveTotal>264</PositiveTotal>
<NegativeTotal>-34</NegativeTotal>
</Total>
Note that the product of REF amount and rate is not included in any of the two totals, as it is neither above nor below the threshold. Similarly, if any other product happens to be equal to the threshold. it too will be excluded.

variable to custom component - flex

I'm trying to pass a variable from my main flex application to a custom component I've created, but haven't really figured anything out.
my variable is just a string - public var test:String = "a test";
my custom component is implement in my main application like this - <ns1:finaltest includeIn="FinalTest" x="26" y="19" />
In my custom component 'finaltest' I'd like just to display the variable 'test'. something like this - finalmessage.text = test;
MainApp.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600" xmlns:local="*"
>
<fx:Script>
<![CDATA[
[Bindable]
public var test:String = "a test";
]]>
</fx:Script>
<local:FinalTest finalMessage="{test}" />
</s:Application>
FinalTest.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="400" height="300"
>
<fx:Script>
<![CDATA[
[Bindable]
public var finalMessage:String;
]]>
</fx:Script>
<s:Label text="{finalMessage}" />
</s:Group>

How can I change (from JavaScript) the title of a XUL window?

In a xulrunner app, I seem to be unable to set the title from JavaScript. I have tried setting in these two ways:
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="mywindow" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="go();">
<!-- your code here -->
<script type="application/x-javascript">
<![CDATA[
function go(){
document.getElementById("mywindow").title="blar";
document.getElementById("mywindow").setAttribute("title","blar");
}
]]>
</script>
</window>
DOM Inspector shows that the title attribute does get updated, but it does not show up on screen.
[CDATA[
function entry_onLoad()
{
document.title = "MyTitle"
}
addEventListener("load", entry_onLoad, false)
]]>
This works
It appears that after the page loads one cannot change the window. If there is a way, I'd be interested to know it.. but this does work:
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="mywindow" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >
<script type="application/x-javascript">
<![CDATA[
function go(){
document.getElementById("mywindow").title="blar";
}
go();
]]>
</script>
</window>