Solved

How to update multiple attributes in an element in the XMLUpdater from an FME list?

  • 17 January 2020
  • 9 replies
  • 30 views

Badge +2

Hi everyone.

 

I am new to XML and am having some difficulties using the XMLUpdater and XQuery. My issue is around updating 3 attributes within an xml element from 3 attributes in an FME list to create multiple children. When I do this for a record which has say 2 items in the list it’s producing 9 children instead of 2, do I need to group my data somewhere in my XQuery?

 

I’ve attached a sample workbench and data.

 

I am reading an Excel document, then creating a list of all LCS_Codes and their measures per TAC_Code. I then want this list to form the children of a location element within my XML. So I’d hope to go from something like this:

 

Input table:

To this output XML text:

 

<tractionCurrentSection id="M58">

<location>

<part idEl="B077/MSBFA" startPos="0" endPos="149.302"></part>

<part idEl="B077/MSBLO" startPos="0" endPos="133.761"></part>

</location>

 

However I’m getting this:

 

<tractionCurrentSection id="M58">

<location>

<part idEl="B077/MSBFA" startPos="0" endPos="149.302"></part>

<part idEl="B077/MSBFA" startPos="0" endPos="133.761"></part>

<part idEl="B077/MSBFA" startPos="0" endPos="149.302"></part>

<part idEl="B077/MSBFA" startPos="0" endPos="133.761"></part>

<part idEl="B077/MSBLO" startPos="0" endPos="149.302"></part>

<part idEl="B077/MSBLO" startPos="0" endPos="133.761"></part>

<part idEl="B077/MSBLO" startPos="0" endPos="149.302"></part>

<part idEl="B077/MSBLO" startPos="0" endPos="133.761"></part>

</location>

</tractionCurrentSection>

 

I think the above is putting each part of the list to each part of the list, hence me having 9 children instead of 2 for the 3 attributes I’m updating. Is there a way I can tell the Xquery to group by the list entry instead?

 

XQuery:

 

<location>{

for $list in fme:get-list-attribute("_list{}.LCS_CODE") for $Startlist in fme:get-list-attribute("_list{}.Start Meterage 1") for $Endlist in fme:get-list-attribute("_list{}.End Meterage 1")

return <part idEl="{$list}" startPos="{$Startlist}" endPos="{$Endlist}" />

}</location>

 

A bit of a side second question…. In the example outputs from the customer I have the XML for the “part” element will just end /> (below), which is what I have put in the XMLUpdater (<part idEl="{$list}" startPos="{$Startlist}" endPos="{$Endlist}" />) but my output seems to be ></part> after my attributes, does this matter? I’ve been given a specific XSD to follow.

 

Example desired output

<location>

<part id=”D202/DEBLO” startPos=”0.00” endPos=”158.44”/>

<part id=”D203/DEBLO” startPos=”0.00” endPos=”130.77”/>

<part id=”D204/DEBLO” startPos=”54.98” endPos=”1097.19”/>

</location>

 

My current output

<location>

<part idEl="B077/MSBFA" startPos="0" endPos="149.302"></part>

<part idEl="B077/MSBLO" startPos="0" endPos="133.761"></part>

</location>

 

 

As a bit of background info this is part of a larger project where I have been given a rather massive XSD to map several of our GIS and Excel datasets to, this is just for one particular dataset. As I say I’m totally new to XML and have read through the W3 schools info to get a bit more acquainted but if anyone knows any other FME-XML specific resources it’s appreciated!

 

 

Thanks in advance!

icon

Best answer by takashi 18 January 2020, 00:59

View original

9 replies

Userlevel 2
Badge +17

Hi @stephstedman, nested for statements would cause such duplication. Try this expression instead.

<location>{
    let $s := fme:get-list-attribute("_list{}.Start Meterage 1")
    let $e := fme:get-list-attribute("_list{}.End Meterage 1")
    for $code at $i in fme:get-list-attribute("_list{}.LCS_CODE")
    return
    <part idEl="{$code}" startPos="{$s[$i]}" endPos="{$e[$i]}" />
}</location>

 

Alternatively you can also generate your required result using just an XMLTempleter without using the XMLUpdater. This workspace example contains Plan B and Plan C that demonstrate the way.

tcs-to-xml-sample-2.fmwt (FME 2019.1.1)

Hope this helps.

Badge +2

Hi @stephstedman, nested for statements would cause such duplication. Try this expression instead.

<location>{
    let $s := fme:get-list-attribute("_list{}.Start Meterage 1")
    let $e := fme:get-list-attribute("_list{}.End Meterage 1")
    for $code at $i in fme:get-list-attribute("_list{}.LCS_CODE")
    return
    <part idEl="{$code}" startPos="{$s[$i]}" endPos="{$e[$i]}" />
}</location>

 

Alternatively you can also generate your required result using just an XMLTempleter without using the XMLUpdater. This workspace example contains Plan B and Plan C that demonstrate the way.

tcs-to-xml-sample-2.fmwt (FME 2019.1.1)

Hope this helps.

That's perfect, exactly what I needed it to do.  Thanks so much for your help @takashi

Badge +1

Hi @takashi, I have a similar question about the XMLUpdater. I want to get the following xml output:

<group id="X" category="line">

 

<section id="A">

 

<section id="B">

 

<section id="C">

 

</group>

I have created the following list using listbuilder grouping on ID and CATEGORY attributes: _list{}.CODE

 

In the XMLUpdater I have input the following parameters:

Group Update Features By: ID and CATEGORY

Update Type: Replace

XML Path: //group

Value Type: XML/XQuery

Value:

<group>{id="fme:get-attribute("ID")" category="fme:get-attribute("CATEGORY")"

 

for $code in fme:get-list-attribute("_list{}.CODE")

 

return

 

<section id="{$code}"/>

 

}</group>

 

However, this does not seem to be working. Can you please have a look and let me know if I am missing something?

Thanks,

Userlevel 2
Badge +17

Hi @takashi, I have a similar question about the XMLUpdater. I want to get the following xml output:

 <group id="X" category="line">

 

 <section id="A">

 

 <section id="B">

 

 <section id="C">

 

 </group>

I have created the following list using listbuilder grouping on ID and CATEGORY attributes: _list{}.CODE

 

In the XMLUpdater I have input the following parameters:

Group Update Features By: ID and CATEGORY

Update Type: Replace

XML Path: //group

Value Type: XML/XQuery

Value:

<group>{id="fme:get-attribute("ID")" category="fme:get-attribute("CATEGORY")"

 

 for $code in fme:get-list-attribute("_list{}.CODE")

 

 return

 

 <section id="{$code}"/>

 

}</group>

 

However, this does not seem to be working. Can you please have a look and let me know if I am missing something?

Thanks,

Hi @aquamarine, close, but wrong. Try this expression and take a closer look at what is different from your expression.

<group id="{fme:get-attribute("ID")}" category="{fme:get-attribute("CATEGORY")}">{
    for $code in fme:get-list-attribute("_list{}.CODE")
    return
    <section id="{$code}"/>
}</group>
Badge +1

HI Takashi

Thanks I see I had some issues with the syntax. I have now fixed that but I am unable to get the content in the XMLUpdater to replace that in the XMLTemplater. Perhaps I have the Update Type and/or XML Path incorrect?

This was the code in the original XMLTemplater:

<base xmlns:xsi=http://www.sss xmlns:rsml=http://www.sss xmlns=http://www.sss>

 

<group id="{fme:get-attribute("ID")}" category="{fme:get-attribute("CATEGORY")}" level="" name="" description="">

 

<section id="{fme:get-attribute("CODE")}" localStart="" category="" level="" name="" description="">

 

</section>

 

<group/>

 

</group>

 

</base>

Thanks

Userlevel 2
Badge +17

HI Takashi

Thanks I see I had some issues with the syntax. I have now fixed that but I am unable to get the content in the XMLUpdater to replace that in the XMLTemplater. Perhaps I have the Update Type and/or XML Path incorrect?

This was the code in the original XMLTemplater:

<base xmlns:xsi=http://www.sss xmlns:rsml=http://www.sss xmlns=http://www.sss>

 

<group id="{fme:get-attribute("ID")}" category="{fme:get-attribute("CATEGORY")}" level="" name="" description="">

 

<section id="{fme:get-attribute("CODE")}" localStart="" category="" level="" name="" description="">

 

</section>

 

<group/>

 

</group>

 

</base>

Thanks

Unfortunately the template expression causes an error so cannot test the subsequent XMLUpdater. Please post a correct expression.

Badge +1

Unfortunately the template expression causes an error so cannot test the subsequent XMLUpdater. Please post a correct expression.

actually the XMLupdater does work now. I didn't fix the syntax properly the first time.

Hi @stephstedman, nested for statements would cause such duplication. Try this expression instead.

<location>{
    let $s := fme:get-list-attribute("_list{}.Start Meterage 1")
    let $e := fme:get-list-attribute("_list{}.End Meterage 1")
    for $code at $i in fme:get-list-attribute("_list{}.LCS_CODE")
    return
    <part idEl="{$code}" startPos="{$s[$i]}" endPos="{$e[$i]}" />
}</location>

 

Alternatively you can also generate your required result using just an XMLTempleter without using the XMLUpdater. This workspace example contains Plan B and Plan C that demonstrate the way.

tcs-to-xml-sample-2.fmwt (FME 2019.1.1)

Hope this helps.

Hi, Can you share the tcs-to-xml-sample-2.fmwt as I am trying to do something similar. Thx

Userlevel 3
Badge +13

Hi, Can you share the tcs-to-xml-sample-2.fmwt as I am trying to do something similar. Thx

Hello @sdave​ , tcs-to-xml-sample-2.fmwt should be available in Takashi's comment now. Best, Kailin.

Reply