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.
Related
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>
Updating this post with new information. I am enclosing the entire XSLT as it is fairly complicated and I am not entirely sure what to withhold to maintain the integrity and cause of the issue. Also, I am going to include the input which I have minimized as much as I could to also maintain integrity of the data. What I am not including is the xsd of the EDI X12 856. this is proprietary and it is also very large. If you are using Biztalk EDI, you already have the schema necessary. If there is information I can provide from this schema that will help answer this question please let me know and I will post anything you need. And if there is somewhere I can put the .xsd like a repository or email, let me know.
The problem is I am trying to reach out to the LIN/LIN11 element and put the contents in the DTM02 element for each iteration. I am either missing syntax to do this or I may need some global variable to spin through the instances. But really new to XSLT and its processing. Could really use some direction and a solution would be great.
<?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 ScriptNS0 userCSharp"
version="1.0"
xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006"
xmlns:ScriptNS0="http://schemas.microsoft.com/BizTalk/2003/ScriptNS0"
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="/ns0:X12_00401_856" />
</xsl:template>
<xsl:template match="/ns0:X12_00401_856">
<xsl:variable name="var:BSN05" select="userCSharp:StringConcat("0001")" />
<xsl:if test="userCSharp:InistrLastPackID()" />
<xsl:variable name="var:OrderNo" select="ns0:HLLoop1[ns0:HL/HL03='O']/ns0:PRF/PRF01" />
<xsl:variable name="var:PurchaseOrderNo" select="ns0:HLLoop1[ns0:HL/HL03='O']/ns0:PRF/PRF06" />
<ns0:X12_00401_856>
<ns0:BSN>
<BSN01>
<xsl:text>00</xsl:text>
</BSN01>
<BSN02>
<xsl:value-of select="ns0:BSN/BSN02/text()" />
</BSN02>
<xsl:variable name="var:v1" select="ScriptNS0:GetEDIDate(string(ns0:BSN/BSN03/text()))" />
<xsl:variable name="var:v2" select="userCSharp:LogicalNe(string($var:v1) , "")" />
<xsl:if test="string($var:v2)='true'">
<xsl:variable name="var:v3" select="ns0:BSN/BSN03/text()" />
<BSN03>
<xsl:value-of select="$var:v3" />
</BSN03>
</xsl:if>
<BSN04>
<xsl:value-of select="ns0:BSN/BSN04/text()" />
</BSN04>
<BSN05>
<xsl:value-of select="$var:BSN05" />
</BSN05>
</ns0:BSN>
<!--Inital the strLastPackID in the begining of the template-->
<!--Shipment-->
<xsl:element name="ns0:HLLoop1">
<xsl:variable name="var:ShipmentHLLoop1" select="ns0:HLLoop1[ns0:HL/HL03='S']" />
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('S')" />
</xsl:element>
<xsl:element name="HL03">S</xsl:element>
</xsl:element>
<xsl:variable name="var:v35" select="userCSharp:StringConcat('BM')" />
<xsl:variable name="var:v36" select="userCSharp:StringConcat('5774125')" />
<xsl:variable name="var:v37" select="userCSharp:StringConcat('SN')" />
<xsl:variable name="var:v38" select="userCSharp:StringConcat('IA')" />
<xsl:variable name="var:v40" select="$var:v35" />
<xsl:variable name="var:v41" select="$var:v36" />
<xsl:variable name="var:v42" select="$var:v37" />
<xsl:variable name="var:v43" select="ns0:TD3/TD303/text()" />
<xsl:variable name="var:v44" select="$var:v38" />
<xsl:variable name="var:v46" select="ScriptNS0:GetRollaShipmentByOrderNo(string($var:OrderNo/text()))" />
<xsl:variable name="var:v47" select="ScriptNS0:PullElementAfterQualifier('VehID', string($var:v46))" />
<!--Ship To-->
<xsl:element name="ns0:N1Loop1">
<xsl:variable name="var:STN1Loop1" select="$var:ShipmentHLLoop1/ns0:N1Loop1[ns0:N1/N101='ST']" />
<xsl:element name="ns0:N1">
<xsl:element name="N101">ST</xsl:element>
<xsl:element name="N102">
<xsl:value-of select="$var:STN1Loop1/ns0:N1/N102" />
</xsl:element>
<xsl:element name="N103">92</xsl:element>
<xsl:element name="N104">
<xsl:value-of select="$var:STN1Loop1/ns0:N1/N104" />
</xsl:element>
</xsl:element>
<!--End of N1-->
</xsl:element>
<!--End of N1Loop1-->
</xsl:element>
<!--End of HLLoop1-->
<!--Order-->
<xsl:element name="ns0:HLLoop1">
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('O')" />
</xsl:element>
<xsl:element name="HL02">
<xsl:value-of select="userCSharp:ReturnHL02('S')" />
</xsl:element>
<xsl:element name="HL03">O</xsl:element>
</xsl:element>
<!--End HL-->
<xsl:element name="ns0:PRF">
<xsl:element name="PRF01">
<xsl:value-of select="$var:PurchaseOrderNo" />
</xsl:element>
</xsl:element>
<!--End PRF-->
</xsl:element>
<!--End HLLoop1-->
<xsl:for-each select="ns0:HLLoop1">
<!--don't include S or O levels-->
<xsl:if test="ns0:HL/HL03 = 'T' or ns0:HL/HL03 = 'I'">
<!--Pack-->
<xsl:if test="ns0:HL/HL03 = 'T'">
<xsl:element name="ns0:HLLoop1">
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('T')" />
</xsl:element>
<xsl:element name="HL02">
<xsl:value-of select="userCSharp:ReturnHL02('O')" />
</xsl:element>
<xsl:element name="HL03">T</xsl:element>
</xsl:element>
<xsl:element name="ns0:MAN">
<xsl:element name="MAN01">GM</xsl:element>
<xsl:element name="MAN02">
<xsl:value-of select="ns0:MAN/MAN02" />
</xsl:element>
</xsl:element>
<!--End of MAN-->
<xsl:element name="ns0:DTM_2">
<xsl:element name="DTM01">036</xsl:element>
<xsl:element name="DTM02">
<xsl:value-of select="ns0:LIN/LIN11" />
</xsl:element>
</xsl:element>
</xsl:element>
<!--End of HLLoop1 Pack-->
</xsl:if>
<!--Item-->
<xsl:if test="ns0:HL/HL03 = 'I'">
<!--Item-->
<xsl:element name="ns0:HLLoop1">
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('I')" />
</xsl:element>
<xsl:element name="HL02">
<xsl:value-of select="userCSharp:ReturnHL02('T')" />
</xsl:element>
<xsl:element name="HL03">I</xsl:element>
</xsl:element>
<xsl:element name="ns0:LIN">
<xsl:element name="LIN01">
<xsl:value-of select="ns0:LIN/LIN01 div 10000" />
</xsl:element>
<xsl:element name="LIN02">UP</xsl:element>
<xsl:element name="LIN03">
<xsl:value-of select="ns0:LIN/LIN03" />
</xsl:element>
</xsl:element>
<!--End of LIN-->
<xsl:element name="SN1">
<xsl:element name="SN102">
<xsl:value-of select="ns0:SN1/SN102" />
</xsl:element>
<xsl:element name="SN103">EA</xsl:element>
</xsl:element>
<!--End of SN1-->
</xsl:element>
<!--End of HLLoop1 Item-->
</xsl:if>
</xsl:if>
</xsl:for-each>
<!--End of Pack/Item For Each-->
</ns0:X12_00401_856>
</xsl:template>
<msxsl:script language="C#" implements-prefix="userCSharp">
<![CDATA[
int HL01 = 0;
int ShipHL = 0;
int OrdrHL = 0;
int PackHL = 0;
int ItemHL = 0;
//This function increments the hl01 value then stores the value into the
//appropriate "last" object variable. It returns the value of hl01 to the
//XSLT script.
public string ReturnHL01(string LevelCode)
{
HL01 += 1;
if (LevelCode == "S")
ShipHL = HL01;
if (LevelCode == "O")
OrdrHL = HL01;
if (LevelCode == "P")
PackHL = HL01;
if (LevelCode == "I")
ItemHL = HL01;
return HL01.ToString();
}
public string ReplaceMe(string str_Input)
{
return str_Input.Replace("-","");
}
public string ReturnQTY(string str_Qty, string str_QtyPerUOM)
{
string[] strarrayQty = str_Qty.Split('.');
string[] strarrayQtyPerUOM = str_QtyPerUOM.Split('.');
str_Qty = strarrayQty[0];
str_QtyPerUOM = strarrayQtyPerUOM[0];
int int_Qty = Convert.ToInt32(str_Qty);
int int_QtyPerUOM = Convert.ToInt32(str_QtyPerUOM);
return (int_Qty * int_QtyPerUOM).ToString();
}
//This function returns the HL02
public string ReturnHL02(string LevelCode)
{
int retlevel = 0;
if (LevelCode == "S")
retlevel = ShipHL;
if (LevelCode == "O")
retlevel = OrdrHL;
if (LevelCode == "P")
retlevel = PackHL;
if (LevelCode == "I")
retlevel = ItemHL;
return retlevel.ToString();
}
/*This Function used to check if the current pack is the same with previous pack,
if the pack is the same, then return string "1", if it is difference, then return "0" */
string strLastPackID;
public void InistrLastPackID()
{
strLastPackID = "";
}
public string CheckIfTheSamePack(string strCurrentPackID)
{
if (strLastPackID == strCurrentPackID)
{
return "1";
}
else
{
strLastPackID = strCurrentPackID;
return "0";
}
}
public string GetReleaseFromPORelease(string str_PO)
{
if (str_PO.Contains("_"))
{
string[] strarray_PO = str_PO.Split('_');
return strarray_PO[1];
}
else
{
return str_PO;
}
}
public string GetMars856STCode(string str_CustomerNumber, string str_STState)
{
string duns;
if (str_CustomerNumber.Contains("NUTRO"))
{
switch (str_STState)
{
case "CA":
duns = "007134919000Y";
break;
case "TN":
duns = "007134919000U";
break;
default:
duns = "BADDUNS";
break;
}
return duns;
}
else
{
switch (str_STState)
{
case "CA":
duns = "0071349190097";
break;
case "GA":
duns = "0071349190031";
break;
case "TX":
duns = "0071349190079";
break;
case "SC":
duns = "0071349190096";
break;
case "OH":
duns = "0071349190041";
break;
default:
duns = "BADDUNS";
break;
}
return duns;
}
}
public string MathDivide(string val1, string val2)
{
string retval = "";
double d1 = 0;
double d2 = 0;
if (IsNumeric1(val1, ref d1) && IsNumeric1(val2, ref d2))
{
if (d2 != 0)
{
double ret = d1 / d2;
retval = ret.ToString();
}
}
return retval;
}
public bool IsNumeric1(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 IsNumeric1(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 string StringConcat(string param0)
{
return param0;
}
public bool LogicalNe(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 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 string GetExpirationDate(string str_Mfg_Date, string str_Shelf_Life)
{
DateTime dt = System.Convert.ToDateTime(str_Mfg_Date);
dt = dt.AddDays(System.Convert.ToInt32(str_Shelf_Life));
return dt.ToString("yyyyMMdd");
}
]]></msxsl:script>
</xsl:stylesheet>
input data:
<?xml version="1.0" encoding="utf-8"?>
<ns0:X12_00401_856 xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
<ST>
<ST01>856</ST01>
<ST02>0001</ST02>
</ST>
<ns0:BSN>
<BSN01>00</BSN01>
<BSN02>SID0000378</BSN02>
<BSN03>20160824</BSN03>
<BSN04>172952</BSN04>
<BSN05>0001</BSN05>
</ns0:BSN>
<ns0:HLLoop1>
<ns0:HL>
<HL01>1</HL01>
<HL03>S</HL03>
</ns0:HL>
<ns0:TD1>
<TD101>PLT94</TD101>
<TD102>4</TD102>
<TD106>G</TD106>
<TD107>52448.00</TD107>
<TD108>LB</TD108>
</ns0:TD1>
<ns0:TD5>
<TD502>2</TD502>
<TD503>ANSH</TD503>
<TD504>M</TD504>
</ns0:TD5>
<ns0:TD3>
<TD301>TL</TD301>
<TD309>TRL0000590</TD309>
</ns0:TD3>
<ns0:REF>
<REF01>SN</REF01>
<REF02>SEAL082401</REF02>
</ns0:REF>
<ns0:REF>
<REF01>BM</REF01>
<REF02>10401217</REF02>
</ns0:REF>
<ns0:DTM_2>
<DTM01>011</DTM01>
<DTM02>20160819</DTM02>
</ns0:DTM_2>
<ns0:N1Loop1>
<ns0:N1>
<N101>SF</N101>
<N102>any name</N102>
<N103>92</N103>
<N104>61</N104>
</ns0:N1>
<ns0:N3>
<N301>101 Your WAY</N301>
</ns0:N3>
<ns0:N4>
<N401>Irvine</N401>
<N402>CA</N402>
<N403>91111</N403>
<N404>USA</N404>
</ns0:N4>
</ns0:N1Loop1>
<ns0:N1Loop1>
<ns0:N1>
<N101>ST</N101>
<N102>0010</N102>
<N103>92</N103>
<N104>0010</N104>
</ns0:N1>
<ns0:N3>
<N301>1234 My Way Ct</N301>
</ns0:N3>
<ns0:N4>
<N401>GROVEPORT</N401>
<N402>OH</N402>
<N403>43125</N403>
<N404>USA</N404>
</ns0:N4>
</ns0:N1Loop1>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>2</HL01>
<HL03>O</HL03>
</ns0:HL>
<ns0:PRF>
<PRF01>10401217</PRF01>
<PRF04>20160822</PRF04>
<PRF06>10401217</PRF06>
<PRF07>KN</PRF07>
</ns0:PRF>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>3</HL01>
<HL03>T</HL03>
</ns0:HL>
<ns0:MAN>
<MAN01>GM</MAN01>
<MAN02>L000000000T5</MAN02>
</ns0:MAN>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>4</HL01>
<HL03>I</HL03>
</ns0:HL>
<ns0:LIN>
<LIN01>20000</LIN01>
<LIN02>UP</LIN02>
<LIN03>030111169051</LIN03>
<LIN04>VN</LIN04>
<LIN05>416905</LIN05>
<LIN10>RU</LIN10>
<LIN11>20180614</LIN11>
</ns0:LIN>
<ns0:SN1>
<SN102>32</SN102>
<SN103>EA</SN103>
</ns0:SN1>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>5</HL01>
<HL03>T</HL03>
</ns0:HL>
<ns0:MAN>
<MAN01>GM</MAN01>
<MAN02>L000000000T6</MAN02>
</ns0:MAN>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>6</HL01>
<HL03>I</HL03>
</ns0:HL>
<ns0:LIN>
<LIN01>20000</LIN01>
<LIN02>UP</LIN02>
<LIN03>030111169051</LIN03>
<LIN04>VN</LIN04>
<LIN05>416905</LIN05>
<LIN10>RU</LIN10>
<LIN11>20180614</LIN11>
</ns0:LIN>
<ns0:SN1>
<SN102>32</SN102>
<SN103>EA</SN103>
</ns0:SN1>
</ns0:HLLoop1>
<ns0:CTT>
<CTT01>6</CTT01>
</ns0:CTT>
<SE>
<SE01>79</SE01>
<SE02>0001</SE02>
</SE>
</ns0:X12_00401_856>
Your XSLT is only outputting the DTM node(s) when HL03 = 'T', but your input doc only has LIN/LIN11 where HL03 is something else (I).
If you want to avoid outputting a DTM node when there is no LIN11, then you could do it like so:
<!--Pack-->
<xsl:if test="ns0:HL/HL03 = 'T'">
<xsl:element name="ns0:HLLoop1">
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('T')" />
</xsl:element>
<xsl:element name="HL02">
<xsl:value-of select="userCSharp:ReturnHL02('O')" />
</xsl:element>
<xsl:element name="HL03">T</xsl:element>
</xsl:element>
<xsl:element name="ns0:MAN">
<xsl:element name="MAN01">GM</xsl:element>
<xsl:element name="MAN02">
<xsl:value-of select="ns0:MAN/MAN02" />
</xsl:element>
</xsl:element>
<!--End of MAN-->
<xsl:if test="ns0:LIN/LIN11">
<xsl:element name="ns0:DTM_2">
<xsl:element name="DTM01">036</xsl:element>
<xsl:element name="DTM02">
<xsl:value-of select="ns0:LIN/LIN11"/>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:element>
<!--End of HLLoop1 Pack-->
</xsl:if>
If you need the following LIN11 node, you could use code like this:
<xsl:element name="DTM02">
<xsl:value-of select="following::LIN11[1]"/>
</xsl:element>
But this seems suspicious and prone to getting broken (what if there is no following LIN11, what if it's 10 HL loops down and gets reused multiple times, etc...). You may be best off getting the following HL loop that has HL03 = 'I', perhaps using something like here XSLT: Loop selecting two elements at a time
Is there a way in C++, using Tinyxml , TinyXpath , such that, a string containing :
<ns:abcd>
<ns:defg>
<ns:hijk>
</ns:hijk>
</ns:defg>
</ns:abcd>
transforms to
<abcd>
<defg>
<hijk>
</hijk>
</defg>
</abcd>
EDIT:
I was using Tinyxml and Tinyxpath.
My workflow was :
a) Create a dom-tree using TinyXML
b) Pass dom-tree to Tinyxpath for xpath evaluations
To add namespace removal, I used following function :
void RemoveAllNamespaces(TiXmlNode* node)
{
TiXmlElement* element = node->ToElement();
if(!element){
return;
}
std::string elementName = element->Value();
std::string::size_type idx = elementName.rfind(':');
if(idx != std::string::npos)
{
element->SetValue(elementName.substr( idx + 1).c_str());
}
TiXmlNode* child = element->IterateChildren(NULL);
while(child)
{
RemoveAllNamespaces(child);
child = element->IterateChildren(child);
}
}
So workflow changed to :
a) Create a dom-tree using TinyXML
b) Remove namespace from the domtree using RemoveAllNamespaces(domtree.Root() )
c) Pass modified-dom-tree to Tinyxpath for xpath evaluations
I would employ an XSLT transform here:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="*">
<xsl:element name="{name()}" namespace=""><xsl:apply-templates select="node()|#*"/></xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{name()}" namespace=""><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Note that on elements/attribute, namespace="" clears the namespace. You can also specify a different namespace instead.
With input.xml like
<?xml version="1.0"?>
<ns:abcd xmlns:ns="http://bla/bla">
<ns:defg attr="value">
<ns:hijk>
</ns:hijk>
</ns:defg>
</ns:abcd>
xsltproc xform.xsl input.xml prints:
<abcd>
<defg attr="value">
<hijk>
</hijk>
</defg>
</abcd>
Ok, in response to the edited question, a few notes:
that doesn't actually treat the namespaces (consider xmlns="http://blabla.com/uri" style default namespaces), but that's actually a TinyXml limitation (eek):
Further, TinyXML has no facility for handling XML namespaces. Qualified element or attribute names retain their prefixes, as TinyXML makes no effort to match the prefixes with namespaces.
it doesn't treat attributes (which can also be qualified)
Here's what I'd do a quick & dirty (assumes TIXML_USE_STL as you were supposedly already using):
static inline std::string RemoveNs(std::string const& xmlName)
{
return xmlName.substr(xmlName.find_last_of(":") + 1);
}
void RemoveAllNamespaces(TiXmlNode* node)
{
assert(node);
if (auto element = node->ToElement()) {
element->SetValue(RemoveNs(element->Value()));
for (auto attr = element->FirstAttribute(); attr; attr = attr->Next())
attr->SetName(RemoveNs(attr->Name()));
for (auto child = node->IterateChildren(nullptr); child; child = element->IterateChildren(child))
RemoveAllNamespaces(child);
}
}
On my MSVC test it prints
<?xml version="1.0" standalone="no"?>
<!-- Our: to do list data -->
<ToDo a="http://example.org/uri1">
<!-- Do I need: a secure PDA? -->
<Item priority="1" distance="close">Go to the<bold>Toy store!</bold></Item>
<Item priority="2" distance="none">Do bills</Item>
<Item priority="2" distance="far & back">Look for Evil Dinosaurs!</Item>
</ToDo>
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>
Can you share an XSLT with me which achieves following please?
Input:
<alfa data="abc" xmlns="http://test1.com/">
<mus:beta xmlns:mus="http://test2.com">
<mus:a>1234567897</mus:a>
<mus:s>777666</mus:s>
</mus:beta>
</alfa>
Output should be:
<alfa data="abc" xmlns="http://test1.com/">
<beta xmlns="http://test2.com">
<a>1234567897</a>
<s>777666</s>
</beta>
</alfa>
In fact; the input is generated with XmlBeans; I can not achieve the output with xmlbeans; So i will do a transform with xslt in mediation; however I need a xslt first :) XmlBeans solution is acceptable too. :)
For xmlbeans users; following does not work, fyi:
Map map = new HashMap();
map.put("http://test1.com/","");
map.put("http://test2.com/","");
xo.setSaveSuggestedPrefixes(map);
Cheers,
Kaan
Here is a stylesheet:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:mus="http://test2.com"
exclude-result-prefixes="mus"
version="1.0">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="mus:*">
<xsl:element name="{local-name()}" namespace="namespace-uri()}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
If you explicitly add a namespace declaration to the document, XmlBeans will respect it. You can add a new default namespace mid-document by using the XmlCursor APIs. For example,
XmlObject xobj = XmlObject.Factory.parse(
"<a xmlns='testA'>\n" +
" <B:b xmlns:B='testB'>\n" +
" <B:x>12345</B:x>\n" +
" </B:b>\n" +
"</a>");
// Use xpath with namespace declaration to find <B:b> element.
XmlObject bobj = xobj.selectPath(
"declare namespace B='testB'" +
".//B:b")[0];
XmlCursor cur = null;
try
{
cur = bobj.newCursor();
cur.removeAttribute(new QName("http://www.w3.org/2000/xmlns/", "B"));
cur.toNextToken();
cur.insertNamespace("", "testB");
}
finally
{
cur.dispose();
}
System.out.println(xobj.xmlText());