ESQL XML Creation in IIB - messagebroker

Can someone help me in creating the below xml structure using ESQL in IIB
Input:
<animal>
<animaldomestic>dog<animaldomestic>
<animalwild>cheetah<animalwild>
</animal>
Output:
<animals>
<animal type="domestic">cow</animal>
<animal type="wild">cheetah</animal>
</animals>

SET OuputRoot.XMLNSC.animals.(XMLNSC.Attribute)animal = 'domestic';
SET OutputRoot.XMLNSC.animals.animal = 'cow';
SET OuputRoot.XMLNSC.animals.(XMLNSC.Attribute)animal = 'wild';
SET OutputRoot.XMLNSC.animals.animal = 'cheetah';

I found solution for this.Please find the below code:
SET OutputRoot.XMLNSC.animals.animal[1].(XMLNSC.Attribute)type = 'domestic';
SET OutputRoot.XMLNSC.animals.animal[1]VALUE = InputRoot.XMLNSC.animal.animaldomestic;
SET OutputRoot.XMLNSC.animals.animal[2].(XMLNSC.Attribute)type = 'wild';
SET OutputRoot.XMLNSC.animals.animal[2]VALUE = InputRoot.XMLNSC.animal.animalwild;

If you want universal code:
DECLARE animal REFERENCE TO InputRoot.XMLNSC.animal.*[>];
DECLARE type CHAR;
DECLARE I INTEGER 1;
WHILE LASTMOVE(animal) DO
SET type = SUBSTRING(FIELDNAME(animal) AFTER 'animal');
SET OutputRoot.XMLNSC.animals.animal[I] = FIELDVALUE(animal);
SET OutputRoot.XMLNSC.animals.animal[I].(XMLNSC.Attribute)type = type;
SET I = I + 1;
SET type = '';
MOVE animal NEXTSIBLING;
END WHILE;

#Egorka_nazarov's solution is the best. A couple of improvements are possible, though:
FOR refAnimals AS InputRoot.XMLNSC.animal.*[];
CREATE LASTCHILD OF OutputRoot.XMLNSC.animals
AS refNewAnimal
TYPE NameValue
NAME 'animal'
VALUE FIELDVALUE(refAnimals);
DECLARE type CHARACTER SUBSTRING(FIELDNAME(refAnimals) AFTER 'animal');
SET refNewAnimal.(XMLNSC.Attribute)type = type;
END FOR;
The above code is shorter and less likely to contain bugs (once you have practiced with REFERENCE variables, obviously).

Related

Access any structure field chosen dynamically at run time

I have a problem, so I have a huge table where some fields contain only numbers from 1-20 and I want to move the values of the fields to a new table where there are 3 fields with a name and the number (zjdc01 or zadc01).
Now I want to check the field value from the huge table and append the values to the new fields.
For Example :
CASE LS_ATLAS_DC-ZJDC01.
WHEN 1.
LS_ATLAS-ZJDC01 = LS_ATLAS_DC-ZJDC01.
LS_ATLAS-ZADC01 = LS_ATLAS_DC-ZADC01.
LS_ATLAS-ZBDC01 = LS_ATLAS_DC-ZBDC01.
WHEN 2.
LS_ATLAS-ZJDC02 = LS_ATLAS_DC-ZJDC01.
LS_ATLAS-ZADC02 = LS_ATLAS_DC-ZADC01.
LS_ATLAS-ZBDC02 = LS_ATLAS_DC-ZBDC01.
WHEN 3.
LS_ATLAS-ZJDC03 = LS_ATLAS_DC-ZJDC01.
LS_ATLAS-ZADC03 = LS_ATLAS_DC-ZADC01.
LS_ATLAS-ZBDC03 = LS_ATLAS_DC-ZBDC01.
WHEN 4.
LS_ATLAS-ZJDC04 = LS_ATLAS_DC-ZJDC01.
LS_ATLAS-ZADC04 = LS_ATLAS_DC-ZADC01.
LS_ATLAS-ZBDC04 = LS_ATLAS_DC-ZBDC01.
But this is very exhausting and I think there is another Solution but I dont know if ABAP have something for this.
Maybe some of you have a Solution or have a similiar problem which he solved.
Use ASSIGN COMPONENT name OF STRUCTURE structure TO <field_symbol>.
DATA name TYPE string. " component name
FIELD-SYMBOLS: <zjdc_xx> TYPE any,
<zadc_xx> TYPE any,
<zbdc_xx> TYPE any.
IF number BETWEEN 1 and 4.
name = |ZJDC{ number WIDTH = 2 ALIGN = RIGHT PAD = '0' }|. "<== ZJDC01 to ZJDC04
ASSIGN COMPONENT name OF STRUCTURE ls_atlas TO <zjdc_xx>.
name = |ZADC{ number WIDTH = 2 ALIGN = RIGHT PAD = '0' }|. "<== ZADC01 to ZADC04
ASSIGN COMPONENT name OF STRUCTURE ls_atlas TO <zadc_xx>.
name = |ZBDC{ number WIDTH = 2 ALIGN = RIGHT PAD = '0' }|. "<== ZBDC01 to ZBDC04
ASSIGN COMPONENT name OF STRUCTURE ls_atlas TO <zbdc_xx>.
<zjdc_xx> = LS_ATLAS_DC-ZJDC01.
<zadc_xx> = LS_ATLAS_DC-ZADC01.
<zbdc_xx> = LS_ATLAS_DC-ZBDC01.
ENDIF.

How to parse the config file shown to create a lua table that is desired?

I want to parse a config file which has information like:
[MY_WINDOW_0]
Address = 0xA0B0C0D0
Size = 0x100
Type = cpu0
[MY_WINDOW_1]
Address = 0xB0C0D0A0
Size = 0x200
Type = cpu0
[MY_WINDOW_2]
Address = 0xC0D0A0B0
Size = 0x100
Type = cpu1
into a LUA table as follows
CPU_TRACE_WINDOWS =
{
["cpu0"] = {{address = 0xA0B0C0D0, size = 0x100},{address = 0xB0C0D0A0, size = 0x200},}
["cpu1"] = {{address = 0xC0D0A0B0, size = 0x100},...}
}
I tried my best with some basic LUA string manipulation functions but couldn't get the output that I'm looking for due to repetition of strings in each sections like 'Address',' Size', 'Type' etc. Also my actual config file is huge with 20 such sections.
I got so far, this is basically one section of the code, rest would be just repetition of the logic.
OriginalConfigFile = "test.cfg"
os.execute("cls")
CPU_TRACE_WINDOWS = {}
local bus
for line in io.lines(OriginalConfigFile) do
if string.find(line, "Type") ~= nil then
bus = string.gsub(line, "%a=%a", "")
k,v = string.match(bus, "(%w+) = (%w+)")
table.insert(CPU_TRACE_WINDOWS, v)
end
end
Basically I'm having trouble with coming up with the FINAL TABLE STRUCTURE that I need. v here is the different rvalues of the string "Type". I'm having issues with arranging it in the table. I'm currently working to find a solution but I thought I could ask for help meanwhile.
This should work for you. Just change the filename to wherever you have your config file stored.
f, Address, Size, Type = io.input("configfile"), "", "", ""
CPU_TRACE_WINDOWS = {}
for line in f:lines() do
if line:find("MY_WINDOW") then
Type = ""
Address = ""
Size = ""
elseif line:find("=") then
_G[line:match("^%a+")] = line:match("[%d%a]+$")
if line:match("Type") then
if not CPU_TRACE_WINDOWS[Type] then
CPU_TRACE_WINDOWS[Type] = {}
end
table.insert(CPU_TRACE_WINDOWS[Type], {address = Address, size = Size})
end
end
end
end
It searches for the MY_WINDOW phrase and resets the variable. If the table exists within CPU_TRACE_WINDOWS, then it just appends a new table value, otherwise it just creates it. Note that this is dependent upon Type always being the last entry. If it switches up anywhere, then it will not have all the required information. There may be a cleaner way to do it, but this works (tested on my end).
Edit: Whoops, forgot to change the variables in the middle there if MY_WINDOW matched. That needed to be corrected.
Edit 2: Cleaned up the redundancy with table.insert. Only need it once, just need to make sure the table is created first.

lua dissector for a float variable returns zero

I'm trying to read a float variable from the buffer but i'm getting a zero value.
This is the code i used:
-- Create fields
str_format=string.format
p_Genie.fields = {}
local fields = p_Genie.fields
fields.number_field = ProtoField.float("p_Genie.number", "Number",base.DEC)
function addFloat32(tree, buf, start, name, floatSize)
local rang = buf(start, floatSize)
local ti = tree:add_le(fields.number_field, rang)
ti:set_text(str_format("%s %f", name, rang:le_float()))
return floatSize
end
What am i doing wrong?
Thanks.
I don't think your use of ProtoField.float is correct. According to Section 11.6.7.16 of the Wireshark Developer's Guide, the 3rd argument is an optional valuestring, not a base. Maybe start by fixing that and see if it resolves your problem.

Fighting a bit with lua table indexing

I am new to Lua, and would like to understand the following syntax:
init_state_global = some_integer
rnn_state = {[0] = init_state_global}
My Pythonic interpretation would be that the first element has index 0 and that the value of the element is equal to the variable init_state_global.
However, when I do
print(rnn_state[0])
I get
>> nil
Can someone can help me interpret this:
rnn_state = {[0] = init_state_global}
In Lua, you do it before the expression set(=) and after the array name. Also, Lua uses 1-based index
init_state_global = some_integer
rnn_state = {}
rnn_state[1] = init_state_global;
Perhaps you forgot to declare a variable:
init_state_global = 5
rnn_state = {[0] = init_state_global}
print(rnn_state[0])
it turns out it is easier than I thought.
Even though lua starts indexing at 1, you can set an index ad hoc to zero.
So
rnn_state = {[0] = init_state_global}
means just that,
rnn_state[0] = init_state_global
However, I stated above that
print(rnn_state[0]) was equal to
>> nil
that is because I forgot to declare the variable (in my code, not in the initial thread)
init_state_global = some_integer
:(
So if you declare the variable correctly, the following statement
print(rnn_state[0])
will return
>> some_integer
if you previously declared
init_state_global = some_integer
Another thing (may not be obvious to those of us used to python lists) is that
rnn_state = {}
rnn_state[0] = 4
is the same as
rnn_state = {[0] = 4}

Why can't I use a map's value without having to use a temporary variable?

Ok so this is my scenario:
rascal>map[int, list[int]] g = ();
rascal>g += (1:[2]);
This will result in:
rascal>g[1];
list[int]: [2]
So far so good, but now I wanted to do this, but it didn't work:
rascal>g[1] += 3;
|stdin:///|(2,1,<1,2>,<1,3>): insert into collection not supported on value and int
So I can't directly use the value from g[1] and will have to use a temporary variable like this:
rascal>lst = g[1];
rascal>lst += 3;
rascal>g[1] = lst;
map[int, list[int]]: (1:[2,3])
But doing this everytime I want to extent my list is a drag!
Am I doing something wrong or would this be an awesome feature?
Richard
Good question! + on lists is concatenation not insert, so you could type the following to get the desired effect:
g[1] += [2];

Resources