 |
| XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead. |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|
|

February 6th, 2009, 09:40 PM
|
|
Registered User
|
|
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
XSLT 1.0 Multiple fields to multiple fields
I have an XSLT transformation that I need to do that takes 3 fields from one system and maps them to 3 different fields from system b based upon the values in system A.
Here is the scenario:
System A
FieldA 100 80 90
FieldB abc 123 456
FieldC def ge kkl
System B
LineA wil 999 BBB
LineB 900 888 00
LineC 0 999 AAA
So if System A has a series of FieldA = 100, FieldB = abc, and FieldC = def how do I map this to LineA = wil, lineb = 900, and linec = 0?
|
|

February 7th, 2009, 05:53 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
You need to show your input and output as XML. XSLT doesn't know anything about "fields" - it understands documents, elements, attributes, and text nodes.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

February 7th, 2009, 02:32 PM
|
|
Registered User
|
|
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
Sorry about that. Im using XSLT version 1. Here are the XML files:
Input:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<env:Body>
<ns:Switcher xmlns:ns="http://example.com/webservices/">
<ns:Field1>100</ns:Field1>
<ns:Field2>abc</ns:Field2>
<ns:Field3>def</ns:Field3>
</ns:Switcher>
</env:Body>
</env:Envelope>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<env:Body>
<ns:Contra xmlns:ns="http://example1.com/webservices/">
<ns:Line1>wil</ns:Line1>
<ns:Line2>900</ns:Line2>
<ns:Line3>0</ns:Line3>
</ns:Contra>
</env:Body>
</env:Envelope>
Normally, my XSLT line would look something like this:
<xsl:when test="name()='field1'"><line1><xsl:choose><x sl:when test=".='0'">2</xsl:when><xsl:when test=".='1'">1</xsl:when><xsl:otherwise><xsl:value-of select="." /></xsl:otherwise></xsl:choose></line1></xsl:when>
However, in this particular situation, I have 3 fields that I need to compare together and depending on their values, I then output a defined set of 3 elements and their values.
Like if A=100, B=100, C=100 then 1=9, 2=8, 3=y then if etc., etc. for over 80 sets of groupings. So if any of the sets are present, display the subset of that group, otherwise, we will put in all 00's.
Is this something that is possible in the XSLT version 1?
|
|

February 7th, 2009, 02:49 PM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
Here is a stylesheet that transforms the elements as you describe:
Code:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://example.com/webservices/"
xmlns:ns="http://example1.com/webservices/"
exclude-result-prefixes="ns1">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns1:Switcher">
<ns:Contra>
<xsl:apply-templates select="@* | node()"/>
</ns:Contra>
</xsl:template>
<xsl:template match="ns1:Field1">
<ns:Line1>
<xsl:apply-templates select="@* | node()"/>
</ns:Line1>
</xsl:template>
<xsl:template match="ns1:Field2">
<ns:Line2>
<xsl:apply-templates select="@* | node()"/>
</ns:Line2>
</xsl:template>
<xsl:template match="ns1:Field3">
<ns:Line3>
<xsl:apply-templates select="@* | node()"/>
</ns:Line3>
</xsl:template>
</xsl:stylesheet>
You obviously also want to change the contents of the Fieldx elements but I don't understand the relationship between the old values and the new ones so you have to implement that yourself or at try to describe it.
It might be as easy as adding e.g.
Code:
<xsl:template match="ns1:Field1[. = '100']">
<ns:Line1>wil</ns:Line1>
</xsl:template>
to transform a Field1 element with contents '100' to a Line1 element with contents 'wil' but unfortunately your post does not make it clear to me what you want to achieve.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
|
|

February 7th, 2009, 03:06 PM
|
|
Registered User
|
|
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
Im performing data integration between two systems through a web service. Each system has a set of 3 fields that need to be mapped together in unison. So out of system A, we have Field(1 - 3) that mean a specific kind of test. To map these tests to the test in system B, I have to take the fields from system A Field(1-3) and map them to system B Line(1-3).
Field 1 from system A means nothing by itself. The reference of the test is in all 3 Fields. So lets say for example, Field1 is the class, Field2 is the test type, and field3 is the level. So you will have Math, Addition, 400. In system B the same type of test would be, MM, Add, 600A. So in order for me to do this correctly, I have to use the entire combination of fields from System A and map them with the 3 corresponding fields in System B.
I apologize for the confusion on this.
|
|

February 7th, 2009, 04:07 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
Looks to me as if you should define a table showing the relationship between iinput values and output values:
Code:
<rule>
<input>
<ns:Field1>100</ns:Field1>
<ns:Field2>abc</ns:Field2>
<ns:Field3>def</ns:Field3>
</input>
<output>
<ns:Line1>wil</ns:Line1>
<ns:Line2>900</ns:Line2>
<ns:Line3>0</ns:Line3>
</output>
</rule>
<rule>
,,,,
</rule>
</rules>
and then you can do
Code:
<xsl:template match="ns:Switcher">
<xsl:variable name="rule" select="$rules/rule[input[ns:Line1 = current()/Line1 and ns:Line2 = current()/Line2 and ns:Line3 = current()/Line3]]"/>
<ns:Contra>
<xsl:copy-of select="$rule/output/*"/>
</ns:Contra>
</xsl:template>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

February 7th, 2009, 05:32 PM
|
|
Registered User
|
|
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
Thanks for the feedback. I want to be sure that I have the XSLT setup correctly.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="xsl" version="1.0"
xmlns:ns="https://example.com/webservices/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:output indent="yes" method="xml" />
<xsl:strip-space elements="*" />
<xsl:param name="SOURCE_FILENAME" />
<rules>
<rule>
<input>
<ns:servicecode>100</ns:servicecode>
<ns:referraltype>100</ns:referraltype>
<ns:referralresult>100</ns:referralresult>
</input>
<output>
<ns:Line1>200</ns:Line1>
<ns:Line2>200</ns:Line2>
<ns:Line3>200</ns:Line3>
</output>
</rule>
</rules>
<xsl:template match="ns:Switcher">
<xsl:variable name="rule" select="$rules/rule[input[ns:Line1 = current()/Line1 and ns:Line2 = current()/Line2 and ns:Line3 = current()/Line3]]"/>
<ns:Contra>
<xsl:copy-of select="$rule/output/*"/>
<xsl:when test="name()='grinder'"><hello><xsl:choose><xsl:wh en test="."><xsl:value-of select="." /></xsl:when></xsl:choose></hello></xsl:when>
</ns:Contra>
</xsl:template>
</xsl:stylesheet>
And to it I can pass:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<env:Body>
<ns:Switcher xmlns:ns="https://example1.com/webservices/">
<Field1>100</Field1>
<Field2>100</Field2>
<Field3>100</Field3>
<grinder>100</grinder>
</ns:Switcher>
</env:Body>
</env:Envelope>
When I try the testing of this, I get an error from the web service saying it could not transform the file. Did I do something incorrectly?
|
|

February 7th, 2009, 07:40 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
If you put a data element at the top level of your stylesheet then it must be in a namespace. In XSLT 2.0 it's easiest to put it in a global variable. In 1.0 some people prefer to put it in a separate document read using the document() function, others prefer to put it like you have done in the stylesheet (but namespaced say as <data:rules>) and then read it using document("")/xsl:stylesheet/data:rules.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

February 7th, 2009, 08:35 PM
|
|
Registered User
|
|
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
I have never used document so im a bit confused. I do have the XSLT 2.0 and XPATH 2.0 book, and Ill read up on that command to see how to apply it.
I made the following adjustment to the following:
<data:rules>
<data:rule>
<data:input>
<ns:servicecode>100</ns:servicecode>
<ns:referraltype>100</ns:referraltype>
<ns:referralresult>100</ns:referralresult>
</data:input>
<data:output>
<ns:Line1>200</ns:Line1>
<ns:Line2>200</ns:Line2>
<ns:Line3>200</ns:Line3>
</data:output>
</data:rule>
</data:rules>
Ill read up on how to apply the document command and give the code a shot.
Thanks for your help with this. I appreciate it.
|
|

February 9th, 2009, 02:50 AM
|
|
Registered User
|
|
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
Is there a way to accomplish this by using <xsl:if>? Such as
<xsl:if element = value><xsl:if element2 = value><xsl:if element3 = value>then I can put my 3 fields here of output</xsl:if></xsl:if></xsl:if>
I know that it may sound mundane but if there is a solution like this to accomplish the task, that would be great. The web services software im using is pretty tempermental.
|
|
 |