I have a file which has entried like below
FIELD1,FIELD2
name,ABC
age,29
location,ZZ
name,XYZ
age,33
location,YY
I require the output to be as below. I tried the row-denormalization, but its not giving proper output
name,age,location
ABC,29,ZZ
XYZ,33,YY
Row de-normalizer can produce an output like this, but it requires some identifier for every entity in the input. And the input has to be sorted by this identifier.
So you need first to transform output of your file to following structure:
ID,FIELD1,FIELD2
0,name,ABC
0,age,29
0,location,ZZ
1,name,XYZ
1,age,33
1,location,YY
One of the ways to achieve this is by combining Add sequence (start from 0) and User Defined Java Expression (Set the expression to ID / 3, if you always have exactly three rows corresponding to the same entity).
Then you can use Row denormalizer as on the picture below.
Your transformation will look like this:
The transformation steps xml (just copy it and paste on the transformation canvas):
<?xml version="1.0" encoding="UTF-8"?>
<transformation-steps>
<steps>
<step>
<name>Data Grid</name>
<type>DataGrid</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<fields>
<field>
<name>FIELD1</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
<field>
<name>FIELD2</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
</fields>
<data>
<line> <item>name</item><item>ABC</item> </line>
<line> <item>age</item><item>29</item> </line>
<line> <item>location</item><item>ZZ</item> </line>
<line> <item>name</item><item>XYZ</item> </line>
<line> <item>age</item><item>33</item> </line>
<line> <item>location</item><item>YY</item> </line>
</data>
<cluster_schema/>
<remotesteps> <input> </input> <output> </output> </remotesteps> <GUI>
<xloc>128</xloc>
<yloc>64</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>Row denormaliser</name>
<type>Denormaliser</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<key_field>FIELD1</key_field>
<group>
<field>
<name>ID</name>
</field>
</group>
<fields>
<field>
<field_name>FIELD2</field_name>
<key_value>name</key_value>
<target_name>name</target_name>
<target_type>String</target_type>
<target_format/>
<target_length>-1</target_length>
<target_precision>-1</target_precision>
<target_decimal_symbol/>
<target_grouping_symbol/>
<target_currency_symbol/>
<target_null_string/>
<target_aggregation_type>-</target_aggregation_type>
</field>
<field>
<field_name>FIELD2</field_name>
<key_value>age</key_value>
<target_name>age</target_name>
<target_type>Integer</target_type>
<target_format/>
<target_length>-1</target_length>
<target_precision>-1</target_precision>
<target_decimal_symbol/>
<target_grouping_symbol/>
<target_currency_symbol/>
<target_null_string/>
<target_aggregation_type>-</target_aggregation_type>
</field>
<field>
<field_name>FIELD2</field_name>
<key_value>location</key_value>
<target_name>location</target_name>
<target_type>String</target_type>
<target_format/>
<target_length>-1</target_length>
<target_precision>-1</target_precision>
<target_decimal_symbol/>
<target_grouping_symbol/>
<target_currency_symbol/>
<target_null_string/>
<target_aggregation_type>-</target_aggregation_type>
</field>
</fields>
<cluster_schema/>
<remotesteps> <input> </input> <output> </output> </remotesteps> <GUI>
<xloc>672</xloc>
<yloc>64</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>Add sequence</name>
<type>Sequence</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<valuename>ID</valuename>
<use_database>N</use_database>
<connection/>
<schema/>
<seqname>SEQ_</seqname>
<use_counter>Y</use_counter>
<counter_name/>
<start_at>0</start_at>
<increment_by>1</increment_by>
<max_value>999999999</max_value>
<cluster_schema/>
<remotesteps> <input> </input> <output> </output> </remotesteps> <GUI>
<xloc>272</xloc>
<yloc>64</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>User Defined Java Expression</name>
<type>Janino</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<formula><field_name>ID</field_name>
<formula_string>ID / 3</formula_string>
<value_type>Integer</value_type>
<value_length>-1</value_length>
<value_precision>-1</value_precision>
<replace_field>ID</replace_field>
</formula>
<cluster_schema/>
<remotesteps> <input> </input> <output> </output> </remotesteps> <GUI>
<xloc>432</xloc>
<yloc>64</yloc>
<draw>Y</draw>
</GUI>
</step>
</steps>
<order>
<hop> <from>Data Grid</from><to>Add sequence</to><enabled>Y</enabled> </hop>
<hop> <from>Add sequence</from><to>User Defined Java Expression</to><enabled>Y</enabled> </hop>
<hop> <from>User Defined Java Expression</from><to>Row denormaliser</to><enabled>Y</enabled> </hop>
</order>
<notepads>
</notepads>
<step_error_handling>
</step_error_handling>
</transformation-steps>
And finally, if you need it, you can get rid of the ID column by using Select values step.
Related
I need to setup headers (Authorization) on the REST Client (Post method) in Pentaho.
I'm passing on the Authorization header as a parameter to the REST Client. Then use that variable inside the Headers field.
But I'm not sure I'm doing it right.
First step, set header on constant.
Second step, using header variable on rest client step
when I use postman passing the same headers, it works very well, like this
this is my ktr
I solved my problem just changing REST CLIENT step by HTTP POST, It works very well.
This damn step rest client just doesn't work when you need send a post request with json body.
In the Field area you select the actual value of the parameter you are entering in the header, in the Name area you type in the actual Type of the parameter.
For example you would feed the Field area with a column in the rows before the step and in the Name area you would type Content-Type
The step would receive
Field -------------------------------------------Name
application/xml;charset=utf-8 ---------- Content-Type
EDIT: Image from Comment
EDIT:
KTR -
<?xml version="1.0" encoding="UTF-8"?>
<transformation>
<info>
<name>call itau</name>
<description/>
<extended_description/>
<trans_version/>
<trans_type>Normal</trans_type>
<directory>/</directory>
<parameters>
</parameters>
<log>
<trans-log-table>
<connection/>
<schema/>
<table/>
<size_limit_lines/>
<interval/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>TRANSNAME</id>
<enabled>Y</enabled>
<name>TRANSNAME</name>
</field>
<field>
<id>STATUS</id>
<enabled>Y</enabled>
<name>STATUS</name>
</field>
<field>
<id>LINES_READ</id>
<enabled>Y</enabled>
<name>LINES_READ</name>
<subject/>
</field>
<field>
<id>LINES_WRITTEN</id>
<enabled>Y</enabled>
<name>LINES_WRITTEN</name>
<subject/>
</field>
<field>
<id>LINES_UPDATED</id>
<enabled>Y</enabled>
<name>LINES_UPDATED</name>
<subject/>
</field>
<field>
<id>LINES_INPUT</id>
<enabled>Y</enabled>
<name>LINES_INPUT</name>
<subject/>
</field>
<field>
<id>LINES_OUTPUT</id>
<enabled>Y</enabled>
<name>LINES_OUTPUT</name>
<subject/>
</field>
<field>
<id>LINES_REJECTED</id>
<enabled>Y</enabled>
<name>LINES_REJECTED</name>
<subject/>
</field>
<field>
<id>ERRORS</id>
<enabled>Y</enabled>
<name>ERRORS</name>
</field>
<field>
<id>STARTDATE</id>
<enabled>Y</enabled>
<name>STARTDATE</name>
</field>
<field>
<id>ENDDATE</id>
<enabled>Y</enabled>
<name>ENDDATE</name>
</field>
<field>
<id>LOGDATE</id>
<enabled>Y</enabled>
<name>LOGDATE</name>
</field>
<field>
<id>DEPDATE</id>
<enabled>Y</enabled>
<name>DEPDATE</name>
</field>
<field>
<id>REPLAYDATE</id>
<enabled>Y</enabled>
<name>REPLAYDATE</name>
</field>
<field>
<id>LOG_FIELD</id>
<enabled>Y</enabled>
<name>LOG_FIELD</name>
</field>
<field>
<id>EXECUTING_SERVER</id>
<enabled>N</enabled>
<name>EXECUTING_SERVER</name>
</field>
<field>
<id>EXECUTING_USER</id>
<enabled>N</enabled>
<name>EXECUTING_USER</name>
</field>
<field>
<id>CLIENT</id>
<enabled>N</enabled>
<name>CLIENT</name>
</field>
</trans-log-table>
<perf-log-table>
<connection/>
<schema/>
<table/>
<interval/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>SEQ_NR</id>
<enabled>Y</enabled>
<name>SEQ_NR</name>
</field>
<field>
<id>LOGDATE</id>
<enabled>Y</enabled>
<name>LOGDATE</name>
</field>
<field>
<id>TRANSNAME</id>
<enabled>Y</enabled>
<name>TRANSNAME</name>
</field>
<field>
<id>STEPNAME</id>
<enabled>Y</enabled>
<name>STEPNAME</name>
</field>
<field>
<id>STEP_COPY</id>
<enabled>Y</enabled>
<name>STEP_COPY</name>
</field>
<field>
<id>LINES_READ</id>
<enabled>Y</enabled>
<name>LINES_READ</name>
</field>
<field>
<id>LINES_WRITTEN</id>
<enabled>Y</enabled>
<name>LINES_WRITTEN</name>
</field>
<field>
<id>LINES_UPDATED</id>
<enabled>Y</enabled>
<name>LINES_UPDATED</name>
</field>
<field>
<id>LINES_INPUT</id>
<enabled>Y</enabled>
<name>LINES_INPUT</name>
</field>
<field>
<id>LINES_OUTPUT</id>
<enabled>Y</enabled>
<name>LINES_OUTPUT</name>
</field>
<field>
<id>LINES_REJECTED</id>
<enabled>Y</enabled>
<name>LINES_REJECTED</name>
</field>
<field>
<id>ERRORS</id>
<enabled>Y</enabled>
<name>ERRORS</name>
</field>
<field>
<id>INPUT_BUFFER_ROWS</id>
<enabled>Y</enabled>
<name>INPUT_BUFFER_ROWS</name>
</field>
<field>
<id>OUTPUT_BUFFER_ROWS</id>
<enabled>Y</enabled>
<name>OUTPUT_BUFFER_ROWS</name>
</field>
</perf-log-table>
<channel-log-table>
<connection/>
<schema/>
<table/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>LOG_DATE</id>
<enabled>Y</enabled>
<name>LOG_DATE</name>
</field>
<field>
<id>LOGGING_OBJECT_TYPE</id>
<enabled>Y</enabled>
<name>LOGGING_OBJECT_TYPE</name>
</field>
<field>
<id>OBJECT_NAME</id>
<enabled>Y</enabled>
<name>OBJECT_NAME</name>
</field>
<field>
<id>OBJECT_COPY</id>
<enabled>Y</enabled>
<name>OBJECT_COPY</name>
</field>
<field>
<id>REPOSITORY_DIRECTORY</id>
<enabled>Y</enabled>
<name>REPOSITORY_DIRECTORY</name>
</field>
<field>
<id>FILENAME</id>
<enabled>Y</enabled>
<name>FILENAME</name>
</field>
<field>
<id>OBJECT_ID</id>
<enabled>Y</enabled>
<name>OBJECT_ID</name>
</field>
<field>
<id>OBJECT_REVISION</id>
<enabled>Y</enabled>
<name>OBJECT_REVISION</name>
</field>
<field>
<id>PARENT_CHANNEL_ID</id>
<enabled>Y</enabled>
<name>PARENT_CHANNEL_ID</name>
</field>
<field>
<id>ROOT_CHANNEL_ID</id>
<enabled>Y</enabled>
<name>ROOT_CHANNEL_ID</name>
</field>
</channel-log-table>
<step-log-table>
<connection/>
<schema/>
<table/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>LOG_DATE</id>
<enabled>Y</enabled>
<name>LOG_DATE</name>
</field>
<field>
<id>TRANSNAME</id>
<enabled>Y</enabled>
<name>TRANSNAME</name>
</field>
<field>
<id>STEPNAME</id>
<enabled>Y</enabled>
<name>STEPNAME</name>
</field>
<field>
<id>STEP_COPY</id>
<enabled>Y</enabled>
<name>STEP_COPY</name>
</field>
<field>
<id>LINES_READ</id>
<enabled>Y</enabled>
<name>LINES_READ</name>
</field>
<field>
<id>LINES_WRITTEN</id>
<enabled>Y</enabled>
<name>LINES_WRITTEN</name>
</field>
<field>
<id>LINES_UPDATED</id>
<enabled>Y</enabled>
<name>LINES_UPDATED</name>
</field>
<field>
<id>LINES_INPUT</id>
<enabled>Y</enabled>
<name>LINES_INPUT</name>
</field>
<field>
<id>LINES_OUTPUT</id>
<enabled>Y</enabled>
<name>LINES_OUTPUT</name>
</field>
<field>
<id>LINES_REJECTED</id>
<enabled>Y</enabled>
<name>LINES_REJECTED</name>
</field>
<field>
<id>ERRORS</id>
<enabled>Y</enabled>
<name>ERRORS</name>
</field>
<field>
<id>LOG_FIELD</id>
<enabled>N</enabled>
<name>LOG_FIELD</name>
</field>
</step-log-table>
<metrics-log-table>
<connection/>
<schema/>
<table/>
<timeout_days/>
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>LOG_DATE</id>
<enabled>Y</enabled>
<name>LOG_DATE</name>
</field>
<field>
<id>METRICS_DATE</id>
<enabled>Y</enabled>
<name>METRICS_DATE</name>
</field>
<field>
<id>METRICS_CODE</id>
<enabled>Y</enabled>
<name>METRICS_CODE</name>
</field>
<field>
<id>METRICS_DESCRIPTION</id>
<enabled>Y</enabled>
<name>METRICS_DESCRIPTION</name>
</field>
<field>
<id>METRICS_SUBJECT</id>
<enabled>Y</enabled>
<name>METRICS_SUBJECT</name>
</field>
<field>
<id>METRICS_TYPE</id>
<enabled>Y</enabled>
<name>METRICS_TYPE</name>
</field>
<field>
<id>METRICS_VALUE</id>
<enabled>Y</enabled>
<name>METRICS_VALUE</name>
</field>
</metrics-log-table>
</log>
<maxdate>
<connection/>
<table/>
<field/>
<offset>0.0</offset>
<maxdiff>0.0</maxdiff>
</maxdate>
<size_rowset>10000</size_rowset>
<sleep_time_empty>50</sleep_time_empty>
<sleep_time_full>50</sleep_time_full>
<unique_connections>N</unique_connections>
<feedback_shown>Y</feedback_shown>
<feedback_size>50000</feedback_size>
<using_thread_priorities>Y</using_thread_priorities>
<shared_objects_file/>
<capture_step_performance>N</capture_step_performance>
<step_performance_capturing_delay>1000</step_performance_capturing_delay>
<step_performance_capturing_size_limit>100</step_performance_capturing_size_limit>
<dependencies>
</dependencies>
<partitionschemas>
</partitionschemas>
<slaveservers>
</slaveservers>
<clusterschemas>
</clusterschemas>
<created_user>-</created_user>
<created_date>2018/08/03 16:21:24.490</created_date>
<modified_user>-</modified_user>
<modified_date>2018/08/03 16:21:24.490</modified_date>
<key_for_session_key/>
<is_key_private>N</is_key_private>
</info>
<notepads>
</notepads>
<order>
<hop>
<from>Generate Rows</from>
<to>Calculator</to>
<enabled>Y</enabled>
</hop>
<hop>
<from>Calculator</from>
<to>REST Client</to>
<enabled>Y</enabled>
</hop>
</order>
<step>
<name>Generate Rows</name>
<type>RowGenerator</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<fields>
<field>
<name>call</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<nullif>https://gerador-boletos.itau.com.br/router-gateway-app/public/codigo_barras/registro</nullif>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
<field>
<name>Content-Type</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<nullif>application/json</nullif>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
<field>
<name>accept</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<nullif>application/vnd.itau</nullif>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
<field>
<name>access_token</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<nullif>1fe43b24da7e9b230bb987dbcca6806f</nullif>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
<field>
<name>itau-chave</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<nullif>8c90asc890asc807c89cxcas</nullif>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
<field>
<name>identificador</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<nullif>06017377000130</nullif>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
</fields>
<limit>1</limit>
<never_ending>N</never_ending>
<interval_in_ms>5000</interval_in_ms>
<row_time_field>now</row_time_field>
<last_time_field>FiveSecondsAgo</last_time_field>
<cluster_schema/>
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>64</xloc>
<yloc>48</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>Calculator</name>
<type>Calculator</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<calculation>
<field_name>call_esc</field_name>
<calc_type>ESCAPE_HTML</calc_type>
<field_a>call</field_a>
<field_b/>
<field_c/>
<value_type>String</value_type>
<value_length>-1</value_length>
<value_precision>-1</value_precision>
<remove>N</remove>
<conversion_mask/>
<decimal_symbol/>
<grouping_symbol/>
<currency_symbol/>
</calculation>
<cluster_schema/>
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>176</xloc>
<yloc>48</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>REST Client</name>
<type>Rest</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<applicationType>JSON</applicationType>
<method>GET</method>
<url/>
<urlInField>Y</urlInField>
<dynamicMethod>N</dynamicMethod>
<methodFieldName/>
<urlField>call_esc</urlField>
<bodyField/>
<httpLogin/>
<httpPassword>Encrypted </httpPassword>
<proxyHost/>
<proxyPort/>
<preemptive>N</preemptive>
<trustStoreFile/>
<trustStorePassword>Encrypted </trustStorePassword>
<headers>
<header>
<field>Content-Type</field>
<name>Content-Type</name>
</header>
<header>
<field>accept</field>
<name>accept</name>
</header>
<header>
<field>access_token</field>
<name>access_token</name>
</header>
<header>
<field>itau-chave</field>
<name>itau-chave</name>
</header>
<header>
<field>identificador</field>
<name>identificador</name>
</header>
</headers>
<parameters>
</parameters>
<matrixParameters>
</matrixParameters>
<result>
<name>result</name>
<code/>
<response_time/>
<response_header/>
</result>
<cluster_schema/>
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>272</xloc>
<yloc>48</yloc>
<draw>Y</draw>
</GUI>
</step>
<step_error_handling>
</step_error_handling>
<slave-step-copy-partition-distribution>
</slave-step-copy-partition-distribution>
<slave_transformation>N</slave_transformation>
</transformation>
My Input xml is in below format
<root>
<entity>
<entityrecord>
<field>
<id>Parent</id>
<value>P-1</value>
</field>
<entity>
<entityrecord>
<field>
<id>Child</id>
<value>C-1</value>
</field>
</entityrecord>
<entityrecord>
<field>
<id>Child</id>
<value>C-2</value>
</field>
</entityrecord>
</entity>
</entityrecord>
<entityrecord>
<field>
<id>Parent</id>
<value>P-2</value>
</field>
<entity>
<entityrecord>
<field>
<id>Child</id>
<value>C-1</value>
</field>
</entityrecord>
<entityrecord>
<field>
<id>Child</id>
<value>C-2</value>
</field>
</entityrecord>
<entityrecord>
<field>
<id>Child</id>
<value>C-3</value>
</field>
</entityrecord>
</entity>
</entityrecord>
<entityrecord>
<field>
<id>Parent</id>
<value>P-3</value>
</field>
<entity>
<entityrecord>
<field>
<id>Child</id>
<value>C-1</value>
</field>
</entityrecord>
<entityrecord>
<field>
<id>Child</id>
<value>C-2</value>
</field>
</entityrecord>
<entityrecord>
<field>
<id>Child</id>
<value>C-3</value>
</field>
</entityrecord>
</entity>
</entityrecord>
</entity>
</root>
and my output Format should be
1^P-1
2^C-1
3^C-2
4^P-2
5^C-1
6^C-2
7^C-3
8^P-3
9^C-1
10^C-2
11^C-3
I tried Many different methods to get this done but nothing worked out.I was not able to generate the sequence number.can anyone help me out in this case
Assuming the repeating 6 in the provided output is a mistake, try:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="field">
<xsl:number count="field" level="any"/>
<xsl:text>^</xsl:text>
<xsl:value-of select="value"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
Applied to your example input, the result will be:
1^P-1
2^C-1
3^C-2
4^P-2
5^C-1
6^C-2
7^C-3
8^P-3
9^C-1
10^C-2
11^C-3
Using XSLT 1.0 I need to transform this:
<wine id="_7" grape="chardonnay">
<product>Carneros</product>
<year>1997</year>
<price>10.99</price>
<Method context="_5" attributes="gccxml(msgid=237)">
<Argument location="f0:13"/>
</Method>
<Field id="_3" context="_7" attributes="gccxml(msgid=239)"/>
<Field id="_4" line="19" attributes=""/>
<Method context="_8" attributes="">
<Argument location="f0:13"/>
</Method>
</wine>
into this:
XML Output-1:
<wine grape="chardonnay" msgid="239">
<product>Carneros</product>
<year>1997</year>
<price>10.99</price>
<Method context="_5" attributes="gccxml(msgid=237)">
<Argument location="f0:13"/>
</Method>
<Field id="3" context="_7" attributes="gccxml(msgid=239)"/>
<Field id="4" line="19"/>
<Method context="_8">
<Argument location="f0:13"/>
</Method>
</wine>
The logic on how to accomplish 'XML Output-1' is as follows:
============================================================
- Logic 1:
----------
search for either 'Field[#context]' or 'Method[#context]' nodes that matches the wine[#id].
For instance:
<wine id="_7" grape="chardonnay">
<Field id="_3" context="_7" attributes="gccxml(msgid=239)"/>
To conclude:
The wine[id="_7"] matches Field[context="_7"], so add the attributes="gccxml(msgid=239)"
in 'wine' element (i.e. msgid="239")
Result:
<wine grape="chardonnay" msgid="239">
- Logic 2:
----------
If 'Field' or 'Method' nodes includes attributes="" (null attribute),
then delete the attributes="" in output.
For Instance:
1. <Field id="4" line="19"/>
2. <Method context="_8">
In addition, I need to transfer this:
XML Input-2
<wine id="_5" grape="chardonnay">
<product>Carneros</product>
<year>1997</year>
<price>10.99</price>
<Field id="_9" line="19" attributes=""/>
<Method context="_5" attributes="gccxml(msgid=235)">
<Argument location="f0:13"/>
</Method>
<Field id="_3" context="_7" attributes="gccxml(msgid=239)"/>
<Field id="_4" line="19" attributes=""/>
</wine>
Into this
XML Output-2:
<wine grape="chardonnay" msgid="235">
<product>Carneros</product>
<year>1997</year>
<price>10.99</price>
<Field id="_9" line="19"/>
<Method context="_5" attributes="gccxml(msgid=235)">
<Argument location="f0:13"/>
</Method>
<Field id="3" context="_7" attributes="gccxml(msgid=239)"/>
<Field id="4" line="19"/>
</wine>
search for either 'Field[#context]' or 'Method[#context]' nodes that
matches the wine[#id].
That's easy to do by using a key - XSLT's built-in mechanism to handle cross-references. Once that's done, it's just a rerun of your previous question:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="msg" match="Field|Method" use="#context"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:attribute name="msgid">
<xsl:value-of select="substring-before(substring-after(key('msg', #id)/#attributes, 'msgid='), ')')"/>
</xsl:attribute>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Added:
To remove empty attributes of Field and Method elemmnts, simply add an empty template that matches them:
<xsl:template match="#*[parent::Field or parent::Method][not (string())]"/>
I have a mule flow with DataMapper configuration to map XML to JSON, in that I have a requirement to Lookup a CSV file which contains, for example, two columns and four rows to map to one of the JSON output field.
Below are my sample CSV file contents:
Name,Contact
Ram,111-222
Kumar,222-333
John,333-444
I got below exception while running DataMapper:
Element [CSV:CSV]-Pre-Execution of lookup table [CSV:CSV]failed
Error when parsing record #2 field Name
Caused by: java.lang.RuntimeException: Parsing error: Unexpected record delimiter, probably record has too few fields.
When the CSV file contains only one row there is no exception.
Could any one provide me a way to solve the issue? Thanks in advance.
EDIT: Please find the DataMapper configuration
<mule>
<data-mapper:config name="XML_To_JSON_1" transformationGraphPath="xml_to_json_1.grf" doc:name="XML_To_JSON" />
<flow name="mule-csv-lookupFlow1" doc:name="mule-csv-lookupFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9090" doc:name="HTTP" />
<data-mapper:transform config-ref="XML_To_JSON_1" doc:name="XML To JSON" />
</flow>
</mule>
Below is the .grf file
<?xml version="1.0" encoding="UTF-8"?><Graph __version="3.5.0" author="pradeep" created="Wed Dec 03 13:06:48 IST 2014" description="XML To JSON" guiVersion="3.4.4.P" id="1417593604462" licenseCode="Unlicensed" licenseType="Unknown" modified="Wed Dec 03 13:06:48 IST 2014" modifiedBy="pradeep" name="XML_To_JSON" preview-file="${Project_Home}/src/main/resources/employee.xml" revision="1.0" showComponentDetails="false">
<Global>
<Metadata __index="0" __referenceCounter="1" __sourcePath="{}/object/contact" _dataStructure="SINGLE_DIMENSIONAL_COLLECTION" _id="__id" _metadataParentId="4430d2fe-5b06-4e39-b259-492c325fe164" _parent_id="__parent_id" _type="Output" id="f11ab87d-ec49-4034-a277-1e96a57b7925">
<Record fieldDelimiter="," name="contact" recordDelimiter="\n\\|\r\n\\|\r" type="delimited">
<Field __artificialType="_parent_id" __systemManaged="true" name="__parent_id" type="string"/>
<Field __artificialType="_id" __systemManaged="true" name="__id" type="string"/>
<Field __index="0" __sourcePath="{}/object/contact/name" containerType="SINGLE" label="name" name="name" type="string"/>
<Field __index="1" __sourcePath="{}/object/contact/phone" containerType="SINGLE" label="phone" name="phone" type="string"/>
</Record>
</Metadata>
<Metadata _type="Lookup" id="963db4af-a7a1-428c-be6b-39af261e93d4">
<Record fieldDelimiter="," name="CSV" recordDelimiter="\n\\|\r\n\\|\r" type="delimited">
<Field containerType="SINGLE" label="firstname" name="firstname" size="10" type="string"/>
<Field containerType="SINGLE" eofAsDelimiter="true" label="phone" name="phone" size="10" type="string"/>
</Record>
</Metadata>
<Metadata __index="0" __referenceCounter="1" __schemaType="employeeType" __sourcePath="{}/employees/employee" _dataStructure="SINGLE_DIMENSIONAL_COLLECTION" _id="__id" _metadataParentId="80f1c157-e81d-439d-afa8-e475de2dfe36" _parent_id="__parent_id" _type="Input" id="019cda9c-1078-4d00-bdcc-f81a59df5292">
<Record fieldDelimiter="," name="employee" recordDelimiter="\n\\|\r\n\\|\r" type="delimited">
<Field __artificialType="_parent_id" __systemManaged="true" name="__parent_id" type="string"/>
<Field __artificialType="_id" __systemManaged="true" name="__id" type="string"/>
<Field __index="0" __schemaType="employeeType" __sourcePath="{}/employees/employee/#firstname" containerType="SINGLE" label="firstname" name="firstname" type="string"/>
<Field __index="1" __schemaType="employeeType" __sourcePath="{}/employees/employee/#lastname" containerType="SINGLE" label="lastname" name="lastname" type="string"/>
<Field __index="2" __schemaType="employeeType" __sourcePath="{}/employees/employee/#gender" containerType="SINGLE" label="gender" name="gender" type="string"/>
<Field __index="3" __schemaType="employeeType" __sourcePath="{}/employees/employee/#phone" containerType="SINGLE" label="phone" name="phone" type="string"/>
<Field __index="4" __schemaType="employeeType" __sourcePath="{}/employees/employee/#text()" containerType="SINGLE" label="text()" name="text" type="string"/>
</Record>
</Metadata>
<Metadata __filteredMetadata="false" __index="0" __referenceCounter="1" __schemaType="employeesType" __sourcePath="{}/employees" _dataStructure="OBJECT" _id="__id" _type="Input" id="80f1c157-e81d-439d-afa8-e475de2dfe36">
<Record fieldDelimiter="," name="employees" recordDelimiter="\n\\|\r\n\\|\r" type="delimited">
<Field __artificialType="_id" __systemManaged="true" name="__id" type="string"/>
</Record>
</Metadata>
<Metadata __index="0" __referenceCounter="1" __sourcePath="{}/object" _dataStructure="OBJECT" _id="__id" _type="Output" id="4430d2fe-5b06-4e39-b259-492c325fe164">
<Record fieldDelimiter="," name="object" recordDelimiter="\n\\|\r\n\\|\r" type="delimited">
<Field __artificialType="_id" __systemManaged="true" name="__id" type="string"/>
</Record>
</Metadata>
<LookupTable fileURL="D:/1_Ram/DEV/Workspace/mule-workspace/mule-datamapper-lookup/src/main/resources/staff.txt" id="CSV" key="phone" metadata="963db4af-a7a1-428c-be6b-39af261e93d4" name="CSV" type="simpleLookup">
<attr name="lookupType"><![CDATA[CSV]]></attr>
</LookupTable>
<Dictionary>
<Entry id="DictionaryEntry0" input="true" name="inputPayload" output="false" type="object"/>
<Entry id="DictionaryEntry1" input="false" name="outputPayload" output="true" type="object"/>
</Dictionary>
</Global>
<Phase number="0">
<Node enabled="enabled" guiName="Foreach 'employees' -> 'object'" guiX="460" guiY="20" id="FOREACH_EMPLOYEES_OBJECT" transformClass="com.mulesoft.datamapper.transform.MelRecordTransform" type="REFORMAT">
<attr name="melScript"><![CDATA[//MEL
//START -> DO NOT REMOVE
output.__id = input.__id;
//END -> DO NOT REMOVE
]]></attr>
</Node>
<Node enabled="enabled" guiName="Foreach 'employee' -> 'contact'" guiX="460" guiY="120" id="FOREACH_EMPLOYEE_CONTACT" transformClass="com.mulesoft.datamapper.transform.MelRecordTransform" type="REFORMAT">
<attr name="melScript"><![CDATA[//MEL
//START -> DO NOT REMOVE
output.__id = input.__id;
output.__parent_id = input.__parent_id;
//END -> DO NOT REMOVE
output.phone = input.phone + (isnull(lookup("CSV").get([input.firstname])) ? null : lookup("CSV").get([input.firstname]).phone);
output.name = input.lastname + ' ' + input.firstname;]]></attr>
</Node>
<Node cacheInMemory="true" charset="UTF-8" enabled="enabled" fileURL="dict:outputPayload" guiName="JSON WRITER" guiX="900" guiY="20" id="JSON_WRITER0" type="JSON_WRITER">
<attr name="mapping"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<object xmlns:clover="http://www.cloveretl.com/ns/xmlmapping" clover:inPort="0">
<clover:collection clover:name="contact">
<item clover:inPort="1" clover:key="__parent_id" clover:parentKey="__id">
<name>$1.name</name>
<phone>$1.phone</phone>
</item>
</clover:collection>
</object>]]></attr>
<attr name="__isJsonSchema"><![CDATA[false]]></attr>
<attr name="_data_format"><![CDATA[JSON]]></attr>
<attr name="jsonSchemaURL"><![CDATA[./src/main/resources/contacts.json]]></attr>
</Node>
<Node charset="UTF-8" dataPolicy="strict" enabled="enabled" fileURL="dict:inputPayload" guiName="XML READER" guiX="20" guiY="20" id="XML_READER0" type="XML_READER">
<attr name="xmlSchemaURL"><![CDATA[./src/main/resources/employees.xsd]]></attr>
<attr name="mapping"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Context outPort="0" sequenceField="__id" xpath="/employees">
<Context generatedKey="__parent_id" outPort="1" parentKey="__id" sequenceField="__id" xpath="employee">
<Mapping cloverField="firstname" trim="true" xpath="#firstname"/>
<Mapping cloverField="lastname" trim="true" xpath="#lastname"/>
<Mapping cloverField="gender" trim="true" xpath="#gender"/>
<Mapping cloverField="phone" trim="true" xpath="#phone"/>
<Mapping cloverField="text" trim="true" xpath="text()"/>
</Context>
</Context>
]]></attr>
<attr name="_data_format"><![CDATA[XML]]></attr>
<attr name="__rootGlobalElementName"><![CDATA[employees]]></attr>
</Node>
<Edge debugMode="true" fromNode="FOREACH_EMPLOYEES_OBJECT:0" guiBendpoints="" id="Edge1" inPort="Port 0 (in)" metadata="4430d2fe-5b06-4e39-b259-492c325fe164" outPort="Port 0 (out)" toNode="JSON_WRITER0:0"/>
<Edge debugMode="true" fromNode="FOREACH_EMPLOYEE_CONTACT:0" guiBendpoints="" id="Edge3" inPort="Port 1 (in)" metadata="f11ab87d-ec49-4034-a277-1e96a57b7925" outPort="Port 0 (out)" toNode="JSON_WRITER0:1"/>
<Edge debugMode="true" fromNode="XML_READER0:0" guiBendpoints="" id="Edge0" inPort="Port 0 (in)" metadata="80f1c157-e81d-439d-afa8-e475de2dfe36" outPort="Port 0 (out)" toNode="FOREACH_EMPLOYEES_OBJECT:0"/>
<Edge debugMode="true" fromNode="XML_READER0:1" guiBendpoints="" id="Edge2" inPort="Port 0 (in)" metadata="019cda9c-1078-4d00-bdcc-f81a59df5292" outPort="Port 1 (out)" toNode="FOREACH_EMPLOYEE_CONTACT:0"/>
</Phase>
</Graph>
I noticed the following issues in your .grf file:
1. CSV Record fields are firstname and phone while in your actual csv file they are Name and Contact (I assume the CSV sample in your original post matches what in staff.txt file).
2. LookupTable key is phone while you lookup based on name in your phone mapping lookup("CSV").get([input.firstname]).phone
Here is what I have:
<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<fields>
<field name="text1">
<value>First Last</value>
<field name="checkbox1">
<value>yes</value>
</field>
<field name="checkbox2">
<value></value>
</field>
<ids original="xxxxx" modified="1331062234" />
<f href="http://example.com/test.pdf" />
</xfdf>
The text value gets entered in the PDF, but I can't figure out how to get the checkboxes to recognize that they are checked.
<input type="checkbox" name="checkbox_name" value="yes" />
The xfdf value entry needs to match the checkbox value:
<field name="checkbox_name">
<value>yes</value>
</field>