I have an incoming SOAP xml request that I need to transform into XSLT, like so:
<q0:Operation namespace="Provisioning" name="Create" modifier="Data">
<q0:ParameterList>
<q0:StringParameter name="Action">Create</q0:StringParameter>
<q0:StructParameter name="Create">
<q0:StringParameter name="UserID">1234567X</q0:StringParameter>
<q0:StringParameter name="Device1">abcd567890</q0:StringParameter>
<q0:StringParameter name="Contract1">Postpaid</q0:StringParameter>
<q0:StringParameter name="Line1">990108024011900</q0:StringParameter>
<q0:StringParameter name="Device2">efgh567890</q0:StringParameter>
<q0:StringParameter name="Contract2">Postpaid</q0:StringParameter>
<q0:StringParameter name="Line2">990104562499105</q0:StringParameter>
</q0:StructParameter>
</q0:ParameterList>
</q0:Operation>
My transformation XSLT looks something like this:
<xsl:for-each select="//q0:CommandRequestData/q0:Command/q0:Transaction/q0:Operation/q0:ParameterList/q0:StructParameter[@name='Create']">
<xsl:for-each select="q0:StringParameter[@name='UserID']">
<ins:Parameter name="USER_ID" value="{string()}" />
</xsl:for-each>
<xsl:for-each select="q0:StringParameter[@name!='UserID']">
<xsl:choose>
<xsl:when test = "starts-with(@name, 'Device')">
<xsl:variable name="DeviceIndex" select="position()"/>
<ins:Parameter name="DEVICE_ID_{$DeviceIndex}" value="{string()}" />
</xsl:when>
<xsl:when test = "starts-with(@name, 'Contract')">
<xsl:variable name="ContractIndex" select="position()"/>
<ins:Parameter name="CONTRACT_TYPE_{$ContractIndex}" value="{string()}" />
</xsl:when>
<xsl:when test = "starts-with(@name, 'Line')">
<xsl:variable name="LineIndex" select="position()"/>
<ins:Parameter name="LINE_ID_{$LineIndex}" value="{string()}" />
</xsl:when>
<xsl:otherwise>
<ins:Parameter name="NA" value="NA" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
However, for some reason the numbers in my result SOAP xml isn't incrementing properly, as if they're based on a single 'counter' variable instead of multiple 'counter' variables:
<q0:Operation namespace="Provisioning" name="Create" modifier="Data">
<q0:ParameterList>
<q0:StringParameter name="Action">Create</q0:StringParameter>
<q0:StructParameter name="Create">
<q0:StringParameter name="USER_ID">1234567X</q0:StringParameter>
<q0:StringParameter name="DEVICE_ID_1">abcd567890</q0:StringParameter>
<q0:StringParameter name="CONTRACT_TYPE_2">Postpaid</q0:StringParameter>
<q0:StringParameter name="LINE_ID_3">990108024011900</q0:StringParameter>
<q0:StringParameter name="DEVICE_ID_4">efgh567890</q0:StringParameter>
<q0:StringParameter name="CONTRACT_TYPE_5">Postpaid</q0:StringParameter>
<q0:StringParameter name="LINE_ID_6">990104562499105</q0:StringParameter>
</q0:StructParameter>
</q0:ParameterList>
</q0:Operation>
How do I fix this? Preferably without using templates, because I'm not familiar enough with those.
The outgoing SOAP xml result from the transformation should have renamed StringParameters with correct numbering, like so:
<q0:Operation namespace="Provisioning" name="Create" modifier="Data">
<q0:ParameterList>
<q0:StringParameter name="Action">Create</q0:StringParameter>
<q0:StructParameter name="Create">
<q0:StringParameter name="USER_ID">1234567X</q0:StringParameter>
<q0:StringParameter name="DEVICE_ID_1">abcd567890</q0:StringParameter>
<q0:StringParameter name="CONTRACT_TYPE_1">Postpaid</q0:StringParameter>
<q0:StringParameter name="LINE_ID_1">990108024011900</q0:StringParameter>
<q0:StringParameter name="DEVICE_ID_2">efgh567890</q0:StringParameter>
<q0:StringParameter name="CONTRACT_TYPE_2">Postpaid</q0:StringParameter>
<q0:StringParameter name="LINE_ID_2">990104562499105</q0:StringParameter>
</q0:StructParameter>
</q0:ParameterList>
</q0:Operation>
The value of position()
is determined from the position of the current node in the current node-set (or, in XPath 2.0 terminology, the position of the context item within the sequence of items currently being processed). The current node-set is established by your instruction:
<xsl:for-each select="q0:StringParameter[@name!='UserID']">
and it includes all q0:StringParameter
elements whose name
is not "UserID"
.
If you want a specific count for each type of name
, try changing:
<xsl:variable name="DeviceIndex" select="position()"/>
to:
<xsl:variable name="DeviceIndex">
<xsl:number count="q0:StringParameter[starts-with(@name, 'Device')]"/>
</xsl:variable>
and so on for the other types.
Or, since it seems the input already has the correct numbering, you could extract it by:
<xsl:variable name="DeviceIndex" select="substring-after(@name, 'Device')"/>