Hi,
I have a scenario where I have two node sets from which I will have to process the data, in the below code in the source XML I have two node sets - CONTENT1 and CONTENT2; I need to read this and generate a different XML out of this. I have the below code for this and this is working perfectly as expected.
Source XML:
<XMLContent><CONTENT1>
<DATA PRJTID="217" REGID="F_DATA">
<CHILD PNUM="" PKID="" PKID1="" PKID2="" PName1="" PName2="" P_DOMFOR="" DP1="" DP2=""/>
<CHILD PNUM="" PKID="" PKID1="" PKID2="" PName1="" PName2="" P_DOMFOR="" DP1="" DP2=""/>
<CHILD PNUM="" PKID="" PKID1="" PKID2="" PName1="" PName2="" P_DOMFOR="" DP1="" DP2=""/>
<CHILD PNUM="P No" PKID="P Key ID" PName1="Name Line 1" PName2="Name Line 2" P_DOMFOR="Domestic" />
<CHILD PNUM="ROUNDING VAL" PKID="" PKID2="" PName1="TOTALS" PName2="" P_DOMFOR="" DP1="" DP2=""/>
<CHILD PNUM="1" PKID="1" PKID1="" PKID2="" PName1="Name Line 1a" PName2="Name Line 1b"
P_DOMFOR="Domestic" DP1="10" DP2="20"/>
<CHILD PNUM="2" PKID="2" PKID1="" PKID2="" PName1="Name Line 2a" PName2="" P_DOMFOR="Foreign"
DP1="100" DP2="200"/>
<CHILD PNUM="3" PKID="3" PKID1="" PKID2="" PName1="First Middle Last" PName2="" P_DOMFOR="Domestic"
DP1="1000" DP2="2000"/>
</DATA></CONTENT1>
<CONTENT2>
<DATA PRJTID="217" REGID="PDI">
<CHILD PNUM="1" PKID="" PKID1="" PKID2="" PName1="" PName2="" PName3="" PAdd1="" PAdd2="" PCity=""
PID="Form" />
<CHILD PNUM="" PKID="" PKID1="" PKID2="" PName1="" PName2="" PName3="" PAdd1="" PAdd2="" PCity=""
PID="Line" />
<CHILD PNUM="" PKID="" PKID1="" PKID2="" PName1="" PName2="" PName3="" PAdd1="" PAdd2="" PCity=""
PID="Code" />
<CHILD PNUM="P No" PKID="PKey ID" PKID1="Other ID" PKID2="Other ID - 2" PName1="P Name Line 1"
PName2="P Name PAdd1="Street Address 1" PAdd2="Street Address 2" PCity="City" PID=""/>
<CHILD PNUM="" PKID="PDetails" PKID1="" PKID2="" PName1="" PName2="" PName3="" PAdd1="" PAdd2=""
PCity="" PTD_USFORIND="" PTDI_ADDST="" PTDI_ADDZIP="" PID="Fund" PTDI_CUST5="" />
<CHILD PNUM="1" PKID="1" PKID1="" PKID2="" PName1=" Name Line 1# " PName2="Name Line 1b" PName3=""
PAdd1=" 1 Mai$n S.t" PAdd2="Apt 1" PCity="NewCity" PID="1" />
<CHILD PNUM="2" PKID="2" PKID1="" PKID2="" PName1="Name Line 2a" PName2="" PName3="" PAdd1="2 Main St"
PAdd2="" PCity="Berlin" PID="2" />
<CHILD PNUM="3" PKID="3" PKID1="" PKID2="" PName1="First Middle Last" PName2="" PName3="" PAdd1="3
Main St" PAdd2="" PCity="Los Angeles" PID="3" />
</DATA></CONTENT2></XMLContent>
XSLT Code:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:key name="PIR" match="//XMLContent/CONTENT2/DATA/CHILD" use="@PNUM"/>
<xsl:param name="ParamPKeyName" select="''"/>
<xsl:variable name="id-list" select="concat(',', $ParamPKeyName, ',')"/>
<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<xsl:template match="/">
<xsl:choose>
<xsl:when test="$ParamPKeyName=''">
<Return>
<xsl:apply-templates select="XMLContent/CONTENT1/DATA/CHILD[string(number(@PNUM)) != 'NaN' and (@PNUM != '0')]"/>
</Return>
</xsl:when>
<xsl:otherwise>
<Return>
<xsl:apply-templates select="XMLContent/CONTENT1/DATA/CHILD[(string(number(@PNUM)) != 'NaN') and (@PNUM != '') and contains($id-list, concat(',', @PNUM, ','))]"/>
</Return>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="CHILD">
<xsl:variable name="RecordNo">
<xsl:value-of select="position()"/>
</xsl:variable>
<xsl:variable name="PNo" select="@PNUM"/>
<Root>
<ContentValues>
<Name>
<xsl:value-of select="key('PIR', $PNo)/@PName1"/>
</Name>
<City>
<xsl:value-of select="key('PIR', $PNo)/@PCity"/>
</City>
<Value1>
<xsl:value-of select="@DP1"/>
</Value1>
<Value2>
<xsl:value-of select="@DP2"/>
</Value2>
</ContentValues>
</Root>
</xsl:template>
</xsl:stylesheet>
C# Code to call this:
In the below parameters: You can consider the follwing
first parameter - xml will take the sourcexml code mentioned above; path is the xslt file path; sPKId = 1,2,3
private string TransformXML(string xml, string Path, string sPKId)
{
//read XML
TextReader tr1 = new StringReader(xml);
XmlTextReader tr11 = new XmlTextReader(tr1);
XPathDocument xPathDocument = new XPathDocument(tr11);
//read XSLT
XmlTextReader tr22 = new XmlTextReader(Path);
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(tr22);
//create the output stream
StringBuilder sb = new StringBuilder();
TextWriter tw = new StringWriter(sb);
XsltArgumentList args = new XsltArgumentList();
args.AddParam("ParamPKeyName", "", sPKId);
xslt.Transform(xPathDocument, args, tw);
return sb.ToString();
}
The problem or what I am looking at is explained below:
If you see my Source XML, In Content1, the first few attributes will be the same, the attribute PNUM will be unique and this is what I am considering when I am mapping the two node sets in my XSLT(code above); if you look at my XSLT code; I am reading DP1 and DP2 attributes; in the current scenario I know that the attribute names will always be DP1 and DP2 and I have coded my XSLT accordingly; this is working fine; however in the scenario I am looking for there could be more attributes which might be present in the source and I need to read that; the first few attributes will remain the same and I would know them(PNUM="" PKID="" PKID1="" PKID2="" PName1="" PName2="" P_DOMFOR="") but from DP1 onwards it could be dynamic, and I need to pull the value for each of the dynamic attributes; like how I am pulling the value for DP1 and DP2 in my XSLT code; (my Content2 node set is not going to change at all), how to pull the attributes values dynamnically when I do not know; another issue is the code that I have now to pull the values for Name and City in XSLT will have to be there, and I need to additionaly handle this dynamic attributes. I am using XSLT 1.0 only and I can use this only.
I am not sure how to handle this scenario; could you please help me with this. I have re-created the code and if you see any mistakes, kindly apoligize. Looking forward for your help and advice.
<XMLContent><CONTENT1>
<DATA PRJTID="217" REGID="F_DATA">
<CHILD PNUM="" PKID="" PKID1="" PKID2="" PName1="" PName2="" P_DOMFOR="" DP1="" DP2=""/>
<CHILD PNUM="" PKID="" PKID1="" PKID2="" PName1="" PName2="" P_DOMFOR="" DP1="" DP2=""/>
<CHILD PNUM="" PKID="" PKID1="" PKID2="" PName1="" PName2="" P_DOMFOR="" DP1="" DP2=""/>
<CHILD PNUM="P No" PKID="P Key ID" PName1="Name Line 1" PName2="Name Line 2" P_DOMFOR="Domestic" />
<CHILD PNUM="ROUNDING VAL" PKID="" PKID2="" PName1="TOTALS" PName2="" P_DOMFOR="" DP1="" DP2=""/>
<CHILD PNUM="1" PKID="1" PKID1="" PKID2="" PName1="Name Line 1a" PName2="Name Line 1b"
P_DOMFOR="Domestic" DP1="10" DP2="20"/>
<CHILD PNUM="2" PKID="2" PKID1="" PKID2="" PName1="Name Line 2a" PName2="" P_DOMFOR="Foreign"
DP1="100" DP2="200"/>
<CHILD PNUM="3" PKID="3" PKID1="" PKID2="" PName1="First Middle Last" PName2="" P_DOMFOR="Domestic"
DP1="1000" DP2="2000"/>
</DATA></CONTENT1>
Rpaul