Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
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
 
Old February 6th, 2009, 09:40 PM
Registered User
 
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
Default 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?
 
Old February 7th, 2009, 05:53 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

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
 
Old February 7th, 2009, 02:32 PM
Registered User
 
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
Default

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'">&lt;line1&gt;<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>&lt;/line1&gt;</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?
 
Old February 7th, 2009, 02:49 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

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
 
Old February 7th, 2009, 03:06 PM
Registered User
 
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
Default

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.
 
Old February 7th, 2009, 04:07 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

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
 
Old February 7th, 2009, 05:32 PM
Registered User
 
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
Default

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?
 
Old February 7th, 2009, 07:40 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

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
 
Old February 7th, 2009, 08:35 PM
Registered User
 
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
Default

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.
 
Old February 9th, 2009, 02:50 AM
Registered User
 
Join Date: Feb 2009
Posts: 9
Thanks: 1
Thanked 0 Times in 0 Posts
Default

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.





Similar Threads
Thread Thread Starter Forum Replies Last Post
Multiple Form Fields tripster General .NET 2 October 17th, 2007 04:22 AM
Group on multiple fields leep Crystal Reports 2 May 21st, 2004 01:12 AM
Updating multiple Rows from multiple fields in ASP vdm_nana SQL Server ASP 0 April 1st, 2004 04:26 AM
Update multiple fields. slgknjn Classic ASP Databases 6 February 15th, 2004 10:26 AM
Multiple Fields Search Helmut Classic ASP Databases 4 July 15th, 2003 02:47 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.