xsl:for-each-group with a condition producing extra output - xslt

I am working on to produce text output file from an xml. The XML entries will have a node called as LoanAmt whose value could be 0 or more than zero. Now, I have to check two conditions, first of which is to see if the value of LoanAmt is greater than 0, and then if it is I have to sum up the entries of LoanAmt if for unique Participant enntries. In other words if there is only one Participant ID in the whole xml then display the output but if there are more than one Partcipant ID then only one record for each unique Particpant ID should be populated but the LoanAmt within each unique Particpant ID should be summed up and displayed. My issue is that my xslt is working the same way as I want but the groupby and if condition is not working on the first entry of xml where Loan Amt is not greater than zero. So, the first entry that I am getting is being displayed with zero amount and this line should not appear.
This is the XML which is not the complete set but I have taken a sample out of the original one :
<?xml version='1.0' encoding='UTF-8'?>
<Report_Data >
<Report_Entry>
<Participant_ID>033</Participant_ID>
<chk>673.58</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Vana</Last_Name>
<First_Name>Sag</First_Name>
<Middle_Name>N</Middle_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>100.8</PreTaxAmt>
<MatchAmt>100.8</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>037</Participant_ID>
<chk>2167.89</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Pilay</Last_Name>
<First_Name>Saath</First_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>61.81</PreTaxAmt>
<MatchAmt>61.81</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>043</Participant_ID>
<chk>819.78</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>ouphan</Last_Name>
<First_Name>angmala</First_Name>
<Gender_Code>2</Gender_Code>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>84.19</PreTaxAmt>
<MatchAmt>84.18</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>049</Participant_ID>
<chk>2066.54</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Tizili</Last_Name>
<First_Name>ard</First_Name>
<Gender_Code>1</Gender_Code>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>136.37</PreTaxAmt>
<MatchAmt>136.36</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>094</Participant_ID>
<chk>946.71</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>holphakdy</Last_Name>
<First_Name>Meya</First_Name>
<Gender_Code>2</Gender_Code>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>81.25</PreTaxAmt>
<MatchAmt>81.25</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>104</Participant_ID>
<chk>1183.3</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Sai</Last_Name>
<First_Name>Paupl</First_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>234.52</PreTaxAmt>
<MatchAmt>234.52</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>128.18</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>106</Participant_ID>
<chk>185.44</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Leve</Last_Name>
<First_Name>Alen</First_Name>
<Middle_Name>S</Middle_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>61.48</PreTaxAmt>
<MatchAmt>61.47</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>106</Participant_ID>
<chk>0</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Leve</Last_Name>
<First_Name>Alen</First_Name>
<Middle_Name>S</Middle_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>0</PreTaxAmt>
<MatchAmt>0</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>10</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>131</Participant_ID>
<chk>508.92</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>th</Last_Name>
<First_Name>Pa</First_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>0</PreTaxAmt>
<MatchAmt>0</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>153</Participant_ID>
<chk>277.2</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Baer</Last_Name>
<First_Name>Er</First_Name>
<Middle_Name>D</Middle_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>72.39</PreTaxAmt>
<MatchAmt>72.38</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>155</Participant_ID>
<chk>1250.83</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>Piye</Last_Name>
<First_Name>Shirit</First_Name>
<Middle_Name>M</Middle_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>0</PreTaxAmt>
<MatchAmt>0</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>96.3</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>170</Participant_ID>
<chk>0</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>terner</Last_Name>
<First_Name>san</First_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>0</PreTaxAmt>
<MatchAmt>0</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>0</LoanAmt>
</Report_Entry>
<Report_Entry>
<Participant_ID>170</Participant_ID>
<chk>684.05</chk>
<Workers>
<FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
<Last_Name>terner</Last_Name>
<First_Name>san</First_Name>
</Workers>
<End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
<PreTaxAmt>162.31</PreTaxAmt>
<MatchAmt>162.3</MatchAmt>
<RothAmt>0</RothAmt>
<LoanAmt>210.98</LoanAmt>
</Report_Entry>
I am putting my xslt that I have used :
<?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"
version="2.0" xmlns:functx="http://www.functx.com" >
<xsl:variable name="linefeed" select="'
'"/>
<xsl:variable name="filler" select="' '"/>
<xsl:variable name="separator" select="','"/>
<xsl:variable name="spaces"
select="concat(' ',' ',' ',' ',' ',' ',' ',' ',' ')"/>
<xsl:template match="/">
<xsl:call-template name="LoanDataRecord"/>
</xsl:template>
<xsl:template name="LoanDataRecord">
<xsl:for-each-group select="Report_Data/Report_Entry" group-by="if( LoanAmt[. > 0 ] ) then Participant_ID else '' " >
<xsl:variable name="Var1" select="current-grouping-key()"/>
<!-- Plan Number -->
<xsl:value-of select="substring(concat('768002',$filler),1,6)"/>
<xsl:value-of select="$separator"/>
<!-- Participant Number -->
<xsl:value-of select="substring(concat(Participant_ID,$filler),1,9)"/>
<xsl:value-of select="$separator"/>
<!-- Loan Amt -->
<xsl:value-of select="(sum(current-group()/LoanAmt))"/>
<xsl:value-of select="$linefeed"/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
768002,033709571,0
768002,104603206,128.18
and so on
But I do not want to see the first line which has 0 LoanAmt.

The problem is the <xsl:for-each-group /> instruction. Change it to use a predicate:
<xsl:for-each-group select="Report_Data/Report_Entry[LoanAmt > 0 ]"
group-by="Participant_ID">
I tested it with your XML, and it works: http://xsltransform.net/bnnZWu.
By the way, I added <xsl:output method="text" />, as that's what you probably want.

Related

How to set c++ boost graphml node and edge id?

I am using the Boost graph to store a set of nodes and edges and then write it to a graphml format. Whatever I do, I cannot find a way to access or set the node id (n0, n1) or edge id (e0) attributes.
It seems to be automatically set.
Is there a way to access and set it manually ?
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="id" attr.type="int" />
<key id="key1" for="edge" attr.name="length" attr.type="double" />
<key id="key2" for="edge" attr.name="max_speed" attr.type="double" />
<key id="key3" for="node" attr.name="name" attr.type="string" />
<key id="key4" for="edge" attr.name="name" attr.type="string" />
<key id="key5" for="edge" attr.name="source" attr.type="int" />
<key id="key6" for="node" attr.name="station" attr.type="boolean" />
<key id="key7" for="edge" attr.name="target" attr.type="int" />
<key id="key8" for="node" attr.name="theta" attr.type="double" />
<key id="key9" for="node" attr.name="x" attr.type="double" />
<key id="key10" for="node" attr.name="y" attr.type="double" />
<graph id="G" edgedefault="directed" parse.nodeids="canonical" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n0">
<data key="key0">10000</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<node id="n1">
<data key="key0">10001</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<edge id="e0" source="n0" target="n1">
<data key="key1">6.95279e-310</data>
<data key="key2">150</data>
<data key="key4"></data>
<data key="key5">-127787376</data>
<data key="key7">21994</data>
</edge>
</graph>
</graphml>
My graph
typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
GpNode, GpEdge>
DirectedGraph;
Where GpNode and GpEdge are custom class definitions.
Thanks in advance
write_graphml takes a dynamic_properties. Let's configure that:
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
struct GpNode {
int id;
std::string name;
bool station;
double theta;
double x;
double y;
};
struct GpEdge {
double length;
double max_speed;
std::string name;
int source;
int target;
};
using DirectedGraph = boost::adjacency_list<boost::vecS, boost::vecS,
boost::directedS, GpNode, GpEdge>;
int main() {
std::ifstream ifs("input.xml");
DirectedGraph g;
auto n0 = add_vertex(
GpNode{
10000, // id
"node1", // name
0, // station
0, // theta
6.95279e-310, // x
0, // y
}, g);
auto n1 = add_vertex(
GpNode{
10001, // id
"node1", // name
0, // station
0, // theta
6.95279e-310, // x
0, // y
}, g);
/*auto e0 = */add_edge(n0, n1,
GpEdge{
6.95279e-310, // length
150, // max_speed
"", // name
-127787376, // source
21994, // target
}, g);
auto vindex = get(&GpNode::id, g);
boost::dynamic_properties dp;
//dp.property("node_id", vindex);
dp.property("id", vindex);
dp.property("name", get(&GpNode::name, g));
dp.property("station", get(&GpNode::station, g));
dp.property("theta", get(&GpNode::theta, g));
dp.property("x", get(&GpNode::x, g));
dp.property("y", get(&GpNode::y, g));
dp.property("length", get(&GpEdge::length, g));
dp.property("max_speed", get(&GpEdge::max_speed, g));
dp.property("name", get(&GpEdge::name, g));
dp.property("source", get(&GpEdge::source, g));
dp.property("target", get(&GpEdge::target, g));
boost::write_graphml(std::cout, g, dp);
}
Prints
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="id" attr.type="int" />
<key id="key1" for="edge" attr.name="length" attr.type="double" />
<key id="key2" for="edge" attr.name="max_speed" attr.type="double" />
<key id="key3" for="node" attr.name="name" attr.type="string" />
<key id="key4" for="edge" attr.name="name" attr.type="string" />
<key id="key5" for="edge" attr.name="source" attr.type="int" />
<key id="key6" for="node" attr.name="station" attr.type="boolean" />
<key id="key7" for="edge" attr.name="target" attr.type="int" />
<key id="key8" for="node" attr.name="theta" attr.type="double" />
<key id="key9" for="node" attr.name="x" attr.type="double" />
<key id="key10" for="node" attr.name="y" attr.type="double" />
<graph id="G" edgedefault="directed" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n0">
<data key="key0">10000</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<node id="n1">
<data key="key0">10001</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<edge id="e0" source="n0" target="n1">
<data key="key1">6.95279e-310</data>
<data key="key2">150</data>
<data key="key4"></data>
<data key="key5">-127787376</data>
<data key="key7">21994</data>
</edge>
</graph>
</graphml>
Mmm. That took a while. But now I see. I know that write_graphviz_dp assumes node_id is the node id property, but as you can see, I tried and it didn't help
Docs To The Rescue
But, wait, docs show a second overload that also takes VertexIndexMap. Let's.... try that?
boost::write_graphml(std::cout, g, vindex, dp);
Now it prints
Live On Coliru
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="id" attr.type="int" />
<key id="key1" for="edge" attr.name="length" attr.type="double" />
<key id="key2" for="edge" attr.name="max_speed" attr.type="double" />
<key id="key3" for="node" attr.name="name" attr.type="string" />
<key id="key4" for="edge" attr.name="name" attr.type="string" />
<key id="key5" for="edge" attr.name="source" attr.type="int" />
<key id="key6" for="node" attr.name="station" attr.type="boolean" />
<key id="key7" for="edge" attr.name="target" attr.type="int" />
<key id="key8" for="node" attr.name="theta" attr.type="double" />
<key id="key9" for="node" attr.name="x" attr.type="double" />
<key id="key10" for="node" attr.name="y" attr.type="double" />
<graph id="G" edgedefault="directed" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n10000">
<data key="key0">10000</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<node id="n10001">
<data key="key0">10001</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<edge id="e0" source="n10000" target="n10001">
<data key="key1">6.95279e-310</data>
<data key="key2">150</data>
<data key="key4"></data>
<data key="key5">-127787376</data>
<data key="key7">21994</data>
</edge>
</graph>
</graphml>
That's likely as close as you'll get with it. Changing the id type to std::string doesn't prevent the "n" prefix. (I suppose it's to allow edges to have id's colliding with nodes without problems?)

XSLT 1.0 Help Conditional Looping

I have a requirement and below is the case ,
If Input Message Record is null then i have to populate with a empty value in OutPut Message
If Input Message Record is not null then i have to loop
Below is the two different Input messages :
Case one Input : Record is Null
<ns0:Root xmlns:ns0="http://Correlation.Input1">
<company>abc</company>
<Token>1243</Token>
</ns0:Root>
Case two Input : Multiple Record
<ns0:Root xmlns:ns0="http://Correlation.Input1">
<company>abc</company>
<Token>1243</Token>
<Record>
<Name>John</Name>
</Record>
<Record>
<Name>Larry</Name>
</Record>
</ns0:Root>
Desire OutPut For Case 1 :
<ns0:Root xmlns:ns0="http://Correlation.Output">
<Company>abc</Company>
<Token>1243</Token>
<Record>
<Name>Default</Name>
</Record>
</ns0:Root>
Desire OutPut For Case 2 :
<ns0:Root xmlns:ns0="http://Correlation.Output">
<Company>abc</Company>
<Token>1243</Token>
<Record>
<Name>John</Name>
</Record>
<Record>
<Name>Larry</Name>
</Record>
</ns0:Root>
XSLT I have wrote :
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:s0="http://Correlation.Input1" xmlns:ns0="http://Correlation.Output" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:apply-templates select="/s0:Root" />
</xsl:template>
<xsl:template match="/s0:Root">
<xsl:variable name="var:v1" select="count(/s0:Root/Record)" />
<xsl:variable name="var:v2" select="userCSharp:LogicalEq(string($var:v1) , "0")" />
<xsl:variable name="var:v4" select="userCSharp:LogicalNot(string($var:v2))" />
<ns0:Root>
<Company>
<xsl:value-of select="company/text()" />
</Company>
<xsl:if test="Token">
<Token>
<xsl:value-of select="Token/text()" />
</Token>
</xsl:if>
<Record>
<xsl:if test="string($var:v2)='true'">
<xsl:variable name="var:v3" select=""Default"" />
<Name>
<xsl:value-of select="$var:v3" />
</Name>
</xsl:if>
<xsl:if test="string($var:v4)='true'">
<xsl:variable name="var:v5" select=""fgfdg"" />
<Name>
<xsl:value-of select="$var:v5" />
</Name>
</xsl:if>
<xsl:if test="string($var:v4)='true'">
<xsl:variable name="var:v6" select=""fgfdg"" />
<xsl:value-of select="$var:v6" />
</xsl:if>
</Record>
</ns0:Root>
</xsl:template>
<msxsl:script language="C#" implements-prefix="userCSharp"><![CDATA[
public bool LogicalEq(string val1, string val2)
{
bool ret = false;
double d1 = 0;
double d2 = 0;
if (IsNumeric(val1, ref d1) && IsNumeric(val2, ref d2))
{
ret = d1 == d2;
}
else
{
ret = String.Compare(val1, val2, StringComparison.Ordinal) == 0;
}
return ret;
}
public bool LogicalNot(string val)
{
return !ValToBool(val);
}
public bool IsNumeric(string val)
{
if (val == null)
{
return false;
}
double d = 0;
return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d);
}
public bool IsNumeric(string val, ref double d)
{
if (val == null)
{
return false;
}
return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d);
}
public bool ValToBool(string val)
{
if (val != null)
{
if (string.Compare(val, bool.TrueString, StringComparison.OrdinalIgnoreCase) == 0)
{
return true;
}
if (string.Compare(val, bool.FalseString, StringComparison.OrdinalIgnoreCase) == 0)
{
return false;
}
val = val.Trim();
if (string.Compare(val, bool.TrueString, StringComparison.OrdinalIgnoreCase) == 0)
{
return true;
}
if (string.Compare(val, bool.FalseString, StringComparison.OrdinalIgnoreCase) == 0)
{
return false;
}
double d = 0;
if (IsNumeric(val, ref d))
{
return (d > 0);
}
}
return false;
}
]]></msxsl:script>
</xsl:stylesheet>
Couldn't you do simply:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://Correlation.Input1"
exclude-result-prefixes="ns0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ns0:Root">
<ns0:Root xmlns:ns0="http://Correlation.Output">
<xsl:apply-templates/>
<xsl:if test="not(Record)">
<Record>
<Name>Default</Name>
</Record>
</xsl:if>
</ns0:Root>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}" >
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Give this a try. Step through it in you debugger. Let me know about questions. Add the formatting that you want.
<xsl:template match="ns0:Root ">
<xsl:copy>
<xsl:apply-templates select="node()"/>
<xsl:if test="not(Record[1])">
<xsl:element name="Record">
<xsl:element name="Name">
<xsl:value-of select="'Default'"/>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:copy>
</xsl:template>
<xsl:template match="Record">
<xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Name">
<xsl:copy>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
<xsl:template match="company">
<xsl:copy>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
<xsl:template match="Token">
<xsl:copy>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:apply-templates select="node()|#*"/>
</xsl:template>

Cannot find a matching 1-argument function named

I have the following XSLT and using Stylus. No matter what I do I get the following error message for Line number 50.
Cannot find a matching 1-argument function named {http://schemas.microsoft.com/BizTalk/2003/userCSharp}ReplaceYYYMMDDtoXsdDate()
encoding="UTF-8" at the does not help.
Adding msxsl:assembly and msxsl:using do not help
Appreciate hints and help.
Regards, Toraj
<?xml version='1.0' ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp ScriptNS0" version="1.0" xmlns:ns0="http://schemas.microsoft.com/dynamics/2008/01/documents/AdecPOItemArrival"
xmlns:st="http://schemas.microsoft.com/dynamics/2008/01/sharedtypes" xmlns:s0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp" xmlns:ScriptNS0="http://schemas.microsoft.com/BizTalk/2003/ScriptNS0">
<xsl:output indent="yes" omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<xsl:apply-templates select="s0:X12_00401_856" />
</xsl:template>
<!-- Use the following inside BizTalk Scripting Fuctoid - Start -->
<xsl:template name="CopyOrderTemplate" match="s0:X12_00401_856" xmlns:s0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
<xsl:copy>
<xsl:apply-templates select="s0:HLLoop1[.//HL03/text()='O']" />
</xsl:copy>
</xsl:template>
<xsl:template name="WMSJournalTableTemplate" match="s0:HLLoop1[.//HL03/text()='O']">
<ns0:WMSJournalTable class="entity" Number="{.//PRF01}">
<xsl:apply-templates select="following-sibling::s0:HLLoop1[.//HL03/text()='I'][generate-id(preceding-sibling::s0:HLLoop1[.//HL03/text()='O'][1])=generate-id(current())]" />
</ns0:WMSJournalTable>
</xsl:template>
<xsl:template name="WMSJournalTransTemplate" match="s0:HLLoop1[.//HL03/text()='I']">
<ns0:WMSJournalTrans class="entity" Number="{.//LIN01}">
<xsl:variable name="Qty" select="s0:SN1/SN102/text()" />
<ns0:Qty>
<xsl:value-of select="$Qty" />
</ns0:Qty>
<xsl:variable name="TestData" select="../s0:DTM/DTM02/text()" />
<ns0:TestDataTst>
<xsl:value-of select="$TestData" />
</ns0:TestDataTst>
<!-- From BizTalk Validate XSLT
<xsl:variable name="var:v29" select="userCSharp:ReplaceYYYMMDDtoXsdDate(string(../../../s0:DTM/DTM02/text()))" /> -->
<!-- <xsl:variable name="var:v29" select="userCSharp:ReplaceYYYMMDDtoXsdDate(string(../s0:DTM/DTM02/text()))"/> -->
<xsl:variable name="var:v29" select="userCSharp:ReplaceYYYMMDDtoXsdDate($TestData)" />
<ns0:TransDate>
<xsl:value-of select="$var:v29" />
</ns0:TransDate>
<xsl:variable name="VendAccount" select="'13458'" />
<ns0:VendAccount>
<xsl:value-of select="$VendAccount" />
</ns0:VendAccount>
</ns0:WMSJournalTrans>
</xsl:template>
<msxsl:script language="C#" implements-prefix="userCSharp">
<!-- <msxsl:script implements-prefix='userCSharp' language='C#'>
<msxsl:assembly href="C:\Users\toraj.khavari\Documents\StylusProjects\856\Adec.Common.Modification.dll"/>
<msxsl:using namespace="Adec.Common.Modification" />
<msxsl:using namespace="System" />-->
<![CDATA[
/// <summary>
/// Replaces the yyyymmddd date to XSD date.
/// </summary>
/// <param name="stringInput">The string input.</param>
/// <returns></returns>
public string ReplaceYYYMMDDtoXsdDate(string stringInput)
{
System.String resultStr = "NotFound";
string year = null;
string month = null;
string day = null;
try
{
if (!System.String.IsNullOrEmpty(stringInput) && (stringInput.Length > 7))
{
// IsDigitsOnly
foreach (char c in stringInput)
{
if (c < '0' || c > '9')
return resultStr = "Invalid Input string values";
}
year = stringInput.Substring(0, 4);
month = stringInput.Substring(4, 2);
day = stringInput.Substring(6, 2);
resultStr = String.Format("{0}-{1}-{2}", year, month, day);
}
else
{
resultStr = "Invalid Input string values";
}
}
catch
{
resultStr = "ExceptionError in ReplaceYYYMMDDtoXsdDateTime";
}
return resultStr;
}
]]>
</msxsl:script>
<!-- Use the bove inside BizTalk Scripting Fuctoid - END -->
</xsl:stylesheet>
Code attached
Well msxsl:script is a proprietary Microsoft feature implemented in some XSLT 1.0 processor by Microsoft like the various MSXML version (which however don't support calling into .NET languages like C#, you can only call VBScript or JScript extension functions) or like XslCompiledTransform. I don't know which XSLT processors you can use with Stylus Studio but I think by default it uses Saxon and that does not support the Microsoft specific extension to call into C#. So you will need to check whether Stylus Studio allows you to switch to Microsoft's XslCompiledTransform as the XSLT processor.

How to edit the end of the XML document end in Qt (writeEndDocument)?

I write a small program address book, contacts stored in the xml file. Here is the part off the code
void new_engine::main_window::write_to_db(const QString& n, const QString& s)
{
QFile m_db_file(m_db_path);
QString t("User");
m_db_file.open(QIODevice::Append);
QXmlStreamWriter wxml(&m_db_file);
wxml.setAutoFormatting(true);
if(m_size == 1)
{
wxml.writeStartDocument();
wxml.writeStartElement("Persons");
}
wxml.writeStartElement(t);
QString id = QString::number(m_size);
wxml.writeAttribute("id", id);
wxml.writeTextElement("Name", n);
wxml.writeTextElement("Surname", s);
wxml.writeEndElement();
wxml.writeEndDocument();
m_db_file.close();
}
but the problem is that after the first contact of the tag file is closed. here is the result
<?xml version="1.0" encoding="UTF-8"?>
<Persons>
<User id="1">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
</Persons>
<User id="2">
<Name>eqwevxcv</Name>
<Surname>xcvxcx</Surname>
</User>
<User id="3">
<Name>das</Name>
<Surname>dasdasd</Surname>
</User>
but it must be so
<Persons>
<User id="1">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
<User id="2">
<Name>eqwevxcv</Name>
<Surname>xcvxcx</Surname>
</User>
<User id="3">
<Name>das</Name>
<Surname>dasdasd</Surname>
</User>
</Persons>
How can we do this, after each new record will have to change document end ?
This is an example:
void write_to_db(QXmlStreamWriter& writer, QString id, QString name, QString surname)
{
writer.writeStartElement("User");
writer.writeAttribute(QXmlStreamAttribute("id", id));
writer.writeTextElement("Name", name);
writer.writeTextElement("Surname", surname);
writer.writeEndElement();
}
// This can be a file, or whatever iodevice your heart desires.
QString out;
QXmlStreamWriter writer(&out);
writer.writeStartDocument();
writer.writeStartElement("Persons");
write_to_db(writer, "1", "das", "vcvx");
write_to_db(writer, "2", "das", "vcvx");
write_to_db(writer, "3", "das", "vcvx");
writer.writeEndElement(); // Close <persons> tag
writer.writeEndDocument();
The output (using QXmlStreamWriter::setAutoFormatting/Indent):
<?xml version="1.0"?>
<Persons>
<User id="1">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
<User id="2">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
<User id="3">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
</Persons>

Element sorting by attribute

I am new to xsl(t).
After reading quite some topics about this the confusion ist getting bigger than smaller. I have to transform a subsection of an xml-file by an attribute.
<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<Rechnung AuftragsReferenz="" MarketingCode="KAN00" Auftragsart="Normal" Auftragsherkunft="Schriftlich" AnzahlPakete="1" ZuZahlenderBetrag="94.30" SummeNebenerloeseNetto="6.07" SummeNebenerloeseBrutto="6.50" EnthalteneMWST="7.86" BetragNetto="86.44" BetragBrutto="94.30" Rechnungsdatum="25.05.2012" Rechnungsnummer="123456789" Zahlungskanal="Rechnung">
<RechnungArtikelpositionen>
<RechnungArtikelposition EinzelPreisNetto="0.00" EinzelPreisBrutto="0.00" GesamtPreisNetto="0.00" GesamtPreisBrutto="0.00" Menge="1.00">
<Rechnungnebenerloese/>
<RechnungMehrwertsteuer Prozentsatz="19.00" Steuerbetrag="2.87" Nettobetrag="15.08"/>
<Artikelposition Absagekennzeichen="Allein im Rückstand" AbsagekennzeichenId="38" Artikeltyp="Geschenk" ArtikeltypId="8" Zusatztextkennzeichen="1" Zusatztext="" Bestellnummer="82000" Bestellmenge="1.00" Artikelbezeichnung="Dankeschön" Katalogkennzeichen="K4"/>
<Ersatzartikel Zusatztextkennzeichen="" Zusatztext="" Bestellnummer="12345" Bestellmenge="1.00" Artikelbezeichnung="Geschenk: EinGeschenk" Katalogkennzeichen="K4"/>
</RechnungArtikelposition>
<RechnungArtikelposition EinzelPreisNetto="15.08" EinzelPreisBrutto="17.95" GesamtPreisNetto="15.08" GesamtPreisBrutto="17.95" Menge="1.00">
<Rechnungnebenerloese/>
<RechnungMehrwertsteuer Prozentsatz="19.00" Steuerbetrag="2.87" Nettobetrag="15.08"/>
<Artikelposition Absagekennzeichen="Keine Absage" AbsagekennzeichenId="1" Artikeltyp="Verkauf" ArtikeltypId="0" Zusatztextkennzeichen="1" Zusatztext="" Bestellnummer="54321" Bestellmenge="1.00" Artikelbezeichnung="Massageöl Latschenkiefer" Katalogkennzeichen="K4"/>
<Ersatzartikel/>
</RechnungArtikelposition>
<RechnungArtikelposition EinzelPreisNetto="27.99" EinzelPreisBrutto="29.95" GesamtPreisNetto="27.99" GesamtPreisBrutto="29.95" Menge="1.00">
<Rechnungnebenerloese/>
<RechnungMehrwertsteuer Prozentsatz="7.00" Steuerbetrag="4.99" Nettobetrag="71.36"/>
<Artikelposition Absagekennzeichen="Keine Absage" AbsagekennzeichenId="1" Artikeltyp="Verkauf" ArtikeltypId="0" Zusatztextkennzeichen="" Zusatztext="" Bestellnummer="44444" Bestellmenge="1.00" Artikelbezeichnung="Knoblauchkapseln 60 Stück +" Katalogkennzeichen="K4"/>
<Ersatzartikel/>
</RechnungArtikelposition>
<RechnungArtikelposition EinzelPreisNetto="18.64" EinzelPreisBrutto="19.95" GesamtPreisNetto="37.28" GesamtPreisBrutto="39.90" Menge="2.00">
<Rechnungnebenerloese/>
<RechnungMehrwertsteuer Prozentsatz="7.00" Steuerbetrag="4.99" Nettobetrag="71.36"/>
<Artikelposition Absagekennzeichen="Keine Absage" AbsagekennzeichenId="1" Artikeltyp="Verkauf" ArtikeltypId="0" Zusatztextkennzeichen="" Zusatztext="" Bestellnummer="55555" Bestellmenge="2.00" Artikelbezeichnung="Echte Sauerampfer Kapseln 60 St.+" Katalogkennzeichen="K4"/>
<Ersatzartikel/>
</RechnungArtikelposition>
</RechnungArtikelpositionen>
<other things />
</Rechnung>
The "Artikelposition"s should be sorted by "EinzelPreisBrutto"
I tried several variations, the latest being:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:copy-of select="Rechnung">
<xsl:copy-of select="RechnungArtikelpositionen" />
<xsl:apply-templates select="RechnungArtikelposition">
<xsl:sort select="#EinzelPreisBrutto" data-type="number" order="descending"/>
</xsl:apply-templates>
</xsl:copy-of>
</xsl:template>
</xsl:stylesheet>
but no sorting occurs. What am I doing wrong? Thank you for your help in advance.
Your XSLT is not actually currently valid the xsl:copy-of function should not contain any elements within it (It is used just to copy an element 'as-is'
Also, you need to make sure when you apply the templates for RechnungArtikelposition you are positioned on the correct parent element of RechnungArtikelpositionen. In your code sample, the current posistion would be the document element of the XML.
Instead of using xsl:copy-of, try working with the identity template with an extra template to match RechnungArtikelpositionen and then sort the children.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="RechnungArtikelpositionen">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:apply-templates select="RechnungArtikelposition">
<xsl:sort select="#EinzelPreisBrutto" data-type="number" order="descending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When applied to your sample XML, the following is output:
<Rechnung AuftragsReferenz="" MarketingCode="KAN00" Auftragsart="Normal" Auftragsherkunft="Schriftlich" AnzahlPakete="1" ZuZahlenderBetrag="94.30" SummeNebenerloeseNetto="6.07" SummeNebenerloeseBrutto="6.50" EnthalteneMWST="7.86" BetragNetto="86.44" BetragBrutto="94.30" Rechnungsdatum="25.05.2012" Rechnungsnummer="123456789" Zahlungskanal="Rechnung">
<RechnungArtikelpositionen>
<RechnungArtikelposition EinzelPreisNetto="27.99" EinzelPreisBrutto="29.95" GesamtPreisNetto="27.99" GesamtPreisBrutto="29.95" Menge="1.00">
<Rechnungnebenerloese/>
<RechnungMehrwertsteuer Prozentsatz="7.00" Steuerbetrag="4.99" Nettobetrag="71.36"/>
<Artikelposition Absagekennzeichen="Keine Absage" AbsagekennzeichenId="1" Artikeltyp="Verkauf" ArtikeltypId="0" Zusatztextkennzeichen="" Zusatztext="" Bestellnummer="44444" Bestellmenge="1.00" Artikelbezeichnung="Knoblauchkapseln 60 Stück +" Katalogkennzeichen="K4"/>
<Ersatzartikel/>
</RechnungArtikelposition>
<RechnungArtikelposition EinzelPreisNetto="18.64" EinzelPreisBrutto="19.95" GesamtPreisNetto="37.28" GesamtPreisBrutto="39.90" Menge="2.00">
<Rechnungnebenerloese/>
<RechnungMehrwertsteuer Prozentsatz="7.00" Steuerbetrag="4.99" Nettobetrag="71.36"/>
<Artikelposition Absagekennzeichen="Keine Absage" AbsagekennzeichenId="1" Artikeltyp="Verkauf" ArtikeltypId="0" Zusatztextkennzeichen="" Zusatztext="" Bestellnummer="55555" Bestellmenge="2.00" Artikelbezeichnung="Echte Sauerampfer Kapseln 60 St.+" Katalogkennzeichen="K4"/>
<Ersatzartikel/>
</RechnungArtikelposition>
<RechnungArtikelposition EinzelPreisNetto="15.08" EinzelPreisBrutto="17.95" GesamtPreisNetto="15.08" GesamtPreisBrutto="17.95" Menge="1.00">
<Rechnungnebenerloese/>
<RechnungMehrwertsteuer Prozentsatz="19.00" Steuerbetrag="2.87" Nettobetrag="15.08"/>
<Artikelposition Absagekennzeichen="Keine Absage" AbsagekennzeichenId="1" Artikeltyp="Verkauf" ArtikeltypId="0" Zusatztextkennzeichen="1" Zusatztext="" Bestellnummer="54321" Bestellmenge="1.00" Artikelbezeichnung="Massageöl Latschenkiefer" Katalogkennzeichen="K4"/>
<Ersatzartikel/>
</RechnungArtikelposition>
<RechnungArtikelposition EinzelPreisNetto="0.00" EinzelPreisBrutto="0.00" GesamtPreisNetto="0.00" GesamtPreisBrutto="0.00" Menge="1.00">
<Rechnungnebenerloese/>
<RechnungMehrwertsteuer Prozentsatz="19.00" Steuerbetrag="2.87" Nettobetrag="15.08"/>
<Artikelposition Absagekennzeichen="Allein im Rückstand" AbsagekennzeichenId="38" Artikeltyp="Geschenk" ArtikeltypId="8" Zusatztextkennzeichen="1" Zusatztext="" Bestellnummer="82000" Bestellmenge="1.00" Artikelbezeichnung="Dankeschön" Katalogkennzeichen="K4"/>
<Ersatzartikel Zusatztextkennzeichen="" Zusatztext="" Bestellnummer="12345" Bestellmenge="1.00" Artikelbezeichnung="Geschenk: EinGeschenk" Katalogkennzeichen="K4"/>
</RechnungArtikelposition>
</RechnungArtikelpositionen>
<otherthings/>
</Rechnung>