+

Search Tips   |   Advanced Search

SDI, v7.2

Looking up data from a sequential source

Continuing with our tutorial scenario, the next step is to add the lookup from D2. The scenario flow diagram

The Tutorial directory contains a file called PhoneNumbers.xml that will serve as your D2 data source. This file holds a series of XML entries, each with two attributes: 'User' and 'telephoneNo'.

Your job will be to include 'telephoneNo' as part of the data written to the output XML document. Since we can't randomly access this text file to do a Lookup as you could for a database or directory, the correct telephone number for each CSV entry will be found by looping through the file and comparing 'User' with 'FullName' coming from the current CSV entry.

However, 'FullName' is first being computed in the Output Map of the 'Write_XML_File' Connector – in other words, too late to do the comparison. That means you must move this computed Attribute from the Output Map of 'Write_XML_File' to the Input Map of 'Read_CSV_File'. Do this by first dragging the Attribute Map item up from one map to the other. Dragging 'FullName' to the Input Map of your Iterator Connector

Now there will be a 'FullName' Map item in both maps. You need to adjust the Input Map assignment since you are now mapping from the Conn Entry to Work, instead of the other way around as is the case for an Output Map. Do this by double-clicking on 'FullName' under 'Read_CSV_File' and changing the assignment to be:

conn.First + " " + conn.Last
Editing the assignment for 'FullName'

We can also edit the original 'FullName' Output Map item so that its assignment is simply work.FullName since this Attribute will now be available in the Work Entry, thanks to your modified Input Map.

Now re-run the AssemblyLine and check Output.xml to make sure it is unchanged. Once you've confirmed this, you will now use a Loop component to read through the PhoneNumbers.xml file and search for each user's number1.

Start by adding a new component to the Data Flow section, this time choosing the component called ConnectorLoop and then naming it 'TelephoneNumber'. A ConnectorLoop is a looping component that uses a Connector to read information from a data source and then cycles all components attached under it once for each entry returned by that Connector. This is similar to the for-each behavior of an Iterator Connector in the Feed section, which cycles components in the Data Flow section for each entry read.

Drag the new 'TelephoneNumber' ConnectorLoop between the IF branch and the 'Write_XML_File' Connector. Make sure it does not end up inside the IF branch. Drag the ConnectorLoop

Select it now to open its editor, which is similar to a Connector editor.

ConnectorLoop Configuration

The main differences are that the Mode drop-down will only ever contain Iterator and Lookup options. Furthermore, there is a More... button that provides options for limiting the entries cycled, as well as an Initialize drop-down parameter with the three selections: ConnectorLoop Advanced Settings

  • Do Nothing, which means that when this Loop is reached during AL processing then its embedded Connector will not be initialized in any way;
  • Initialize and Select/Lookup, to cause the Connector to be initialized whenever the Loop starts to cycle. Use this option since your ConnectorLoop will be reading from a file and you want it start from the beginning each time;
  • Select/Lookup Only, which is useful when your ConnectorLoop is pointing at a database, directory or some other randomly accessible data source. Re-initializing the connection each time is not necessary in this case. All that must be done is to re-issue the search, which is a Select in the case of Iterator mode, and a Lookup operation for Lookup mode.

Configure the LoopConnector (which is of type 'FileSystem' by default) to read the PhoneNumber.xml file and then select the 'XML Parser'. Now bring up the Attribute Map tab to discover Attributes. Hierarchical Attributes

You will do your mapping at the Attribute level by selecting the 'User' and 'telephoneNo' in the Input Schema and dragging them to the Input Map. Dragging from Schema to Attribute Map

As a result, you will have one mapping rule for an Attribute named "User" and one for "telephoneNo".

We can now close the LoopConnector editor and then add an IF branch underneath it by right-clicking on the ConnectorLoop and choosing Add Component.... Call this IF branch 'Matching name found'. Now add a simple condition that checks if 'User' equals '$FullName'2. Condition editor for IF branch

Whenever a match is found then you will want the ConnectorLoop to exit with the correct values in the 'User' and 'telephoneNo' Attributes. To do this, add a Script component that you name 'Exit loop' and write the following script into:

	system.exitBranch("loop");

But what happens if the ConnectorLoop reaches the end of PhoneNumbers.xml without finding a match? The 'User' and 'telephoneNo' Attributes contain the values read from the last entry in the file, so just checking for empty Attributes won't help. You will need to devise some other way of detecting a failed match.

The answer is to use a script variable as a flag to indicate that a match was found. Do this now by inserting a Script component that you call 'Found user' inside the IF branch, dragging it just before the 'Exit loop' SC. This Script component should contain the following script snippet:

	foundUser = true;
To indicate that a the end of the input file has been reached without finding a match simply select your ConnectorLoop and open the Hooks tab. Figure 10. Scripting the End of Data Hook

Select the Hook called 'End of Data' and enter this script.

	foundUser = false;

The 'End of Data' Hook will only be reached if the Connector attempts to read past the last entry in its connected source. In this case, no match has been found.

Now the AssemblyLine should have these components:

Figure 11. Component list in the AssemblyLine Data Flow section

You should now be able to ascertain whether or not the search was successful by checking your script variable. This is important since whenever no match is found then you must also set a default value for the 'telephoneNo' Attribute; otherwise it will still have the last value read in by the ConnectorLoop.

So add another IF branch immediately following the ConnectorLoop and call it 'NOT foundUser'. Click on the Script button in the IF Branch details area and enter this script to check the value of your script variable:

	! foundUser

The exclamation mark negates the value of foundUser so if it has been set to false in the 'End of Data' Hook of your ConnectorLoop, this branch Condition will evaluate to true.

Figure 12. Scripting a Condition for the IF branch

Insert a new component of type 'Attribute Map' underneath it. Call this Attribute Map component 'Set default telephoneNo' to make its function clear in the context of the AssemblyLine. Now use the Add Attribute button to create a single Attribute named 'telephoneNo' – the same name as that being returned by your ConnectorLoop. Double-click on this Attribute to set up the assignment script:

	"N/A"
This means that any person read from your CSV input and not found in PhoneNumbers.xml will get a 'telephoneNo' value of "N/A"3.

Finally, include this new 'telephoneNo' Attribute in the Output Map of 'Write_XML_File' by dragging it there and then making sure the assignment is:

	work.telephoneNo

Your AssemblyLine should now look like this.

Figure 13. AssemblyLine complete with FOR-EACH Loop

Now run your AL again and examine the log output. Your 'NOT foundUser' branch should have been true twice and false for the other four entries.

Figure 14. Log Output with IF branch statistics

Note that some component names are highlighted (blue) in the AL statistics of the log output. If you Ctrl-click on one with left mouse button it opens the selected component up in the AssemblyLine editor.

As a result, your XML output should look like this:

Figure 15. XML output with 'telephoneNo' Attribute

So far, so good. It's now time to try using Lookup mode to do the join.


Parent topic:

Introducing SDI

1 There are three types of Loop components: 1) The ConnectorLoop, which lets you cycle on data returned by a Connector in Iterator or Lookup mode. This is the type of Loop you will use in this exercise; 2) the ForEachAttributeValueLoop, making it easy to loop through the values of a multi-valued Attribute, such as those you find in systems like Lotus Notes® and LDAP Directories; and 3) the ConditionalLoop, which uses Simple and scripted Conditions – just like those used by Branches – to control cycling.2 The dollar sign is a special character used here to indicate that 'FullName' is not a literal string to match, but rather the value of an Attribute found in the Work Entry.3 If you would prefer these users to have no 'telephoneNo' Attribute at all, simply use an assignment that returns no value. This is done by returning the special value null:

null
This will cause default Null Behavior will remove the Attribute from the Work Entry. As a result, it will not reach the Output Map of your 'Write_XML_File' Connector and therefore not appear in the resulting XML document.