Question

How to differentiate Empty String and <null> value in XQuery/XMLTemplator

  • 10 January 2023
  • 5 replies
  • 76 views

Badge +3

Hi,

 

I was wondering if there is a way in which it is possible to differentiate between an Empty String and a <null> value when using (XQuery in) the XMLTemplator.

 

As an example I created 4 features. The first having a regular string value, and the latter 3 having 'no value', but each a different type of 'no value' (empty string, <null>, <missing>);

imageWhen creating a dummyXML, I would like to be able to be able to handle/create a different 'b' element, based on the value of the attribute b. Let's say I have two fixed elements 'a' and 'c', and I want my dynamic 'b' element to be placed in between these two, then iterating over the different 4 features I would like to obtain the following result;

<dummyXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <a>value_a</a>
    <b>value_b</b>
    <c>value_c</c>
</dummyXML>
<dummyXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <a>value_a</a>
    <b/>
    <c>value_c</c>
</dummyXML>
<dummyXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <a>value_a</a>
    <b xsi:nil="true" nilReason="unknown"/>
    <c>value_c</c>
</dummyXML>
<dummyXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <a>value_a</a>
    
    <c>value_c</c>
</dummyXML>

To do so, I used the following XML/XQuery statement in my XMLTemplator;

<dummyXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <a>value_a</a>
    {
        if ( not(fme:has-attribute("b")) )
        then ()
        else if ( not(fme:get-attribute("b") = "" or fme:get-attribute("b") = "NULL") )
        then (<b>{fme:get-attribute("b")}</b>)
        else if ( fme:get-attribute("b") = "" )
        then (<b/>)
        else if ( fme:get-attribute("b") = "NULL" )
        then (<b xsi:nil="true" nilReason="unknown"/>)
        else ()
    }
    <c>value_c</c>
</dummyXML>

But as you can see this only works if I convert my <null> value first to a string value 'NULL'. I'm wondering if there is maybe also an XQuery function that is able to determine if a value is null. I would have hoped for something similar to fme:has-attribute(), but then e.g. fme:attribute-is-null() or something, but I don't see one in the XQuery Functions documentation page of Safe. 

Maybe there is some other native (non fme) XQuery function that can achieve this?

 

Kind regards,

 

Thijs

 

ps. see also attached sample workspace.


5 replies

Userlevel 3
Badge +17

Hello @thijsknapen​ 

There currently isn't an XQuery function in FME to determine if an attribute is null or not. I have filed this request as an enhancement and will let you know once it has been implemented.

Our development team did mention it is possible to use the fme:get-json-attribute()

XQuery function as it does have special handling for null attributes. The downside is using this function will cause warnings and errors in the log since the attribute does not contain valid JSON which is not ideal. 

<dummyXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <a>value_a</a>
    {
        if ( not(fme:has-attribute("b")) )
        then ()
        else if ( not(fme:get-attribute("b") = "") )
        then (<b>{fme:get-attribute("b")}</b>)
        else if (xs:string(fme:get-json-attribute("b")) = "null")
        then (<b xsi:nil="true" nilReason="unknown"/>)
        else if ( fme:get-attribute("b") = "")
        then (<b/>)
        else ()
    }
    <c>value_c</c>
</dummyXML>

I hope this information helps.

Badge +3

Hello @thijsknapen​ 

There currently isn't an XQuery function in FME to determine if an attribute is null or not. I have filed this request as an enhancement and will let you know once it has been implemented.

Our development team did mention it is possible to use the fme:get-json-attribute()

XQuery function as it does have special handling for null attributes. The downside is using this function will cause warnings and errors in the log since the attribute does not contain valid JSON which is not ideal. 

<dummyXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <a>value_a</a>
    {
        if ( not(fme:has-attribute("b")) )
        then ()
        else if ( not(fme:get-attribute("b") = "") )
        then (<b>{fme:get-attribute("b")}</b>)
        else if (xs:string(fme:get-json-attribute("b")) = "null")
        then (<b xsi:nil="true" nilReason="unknown"/>)
        else if ( fme:get-attribute("b") = "")
        then (<b/>)
        else ()
    }
    <c>value_c</c>
</dummyXML>

I hope this information helps.

Hi @debbiatsafe​ ,

 

Thanks for filing the enhancement request! It would be great if that could be implemented.

 

Regarding the fme:get-json-attribute() XQuery function, I indeed noticed that that does support null values. I suppose that may be part of JSONiq, which is an extention to XQuery? In section 3.1. Simple Datatypes I found that;

JSONiq adds one new data type: js:null, derived from xs:anyAtomicType. js:null has a singleton value space containing the value null [2]. The lexical representation of an instance of js:null is the string "null".

 

Thanks for sharing the workaround. I noticed that it works, but due to the warnings and errors you mentioned, I think I prefer my initial workaround (map <null> to specific string, and check if value equals that string).

 

Also, by parsing the null value that is fetched from the fme:get-json-attribute() function to a string, I think you effectively might do the same. Specifically, you still perform a stringwise comparison, and you wouldn't be able to distinct a string value "null", from a <null> value that can be fetched as a JSON null type and then parsed to the string "null". So, instead of line 8 in your example, I thought about using;

else if (fme:get-json-attribute("b") eq null)

but that doesn't seem to be working for me. I am a bit confused why not. 

 

Specifically, when I use an XMLXQueryExtractor transformer using the statement;

xs:string(jn:null()) eq "null"

it results in 'true' (I think effectively why your workaround works).

 

However, when I then use either

jn:null() eq null

or

null eq null

i get an empty string as a result, where I would have also expected 'true'. 

Specifically, section 6.16. Changes to value comparison semantics of the JSONiq doc would lead me to believe that that should also result in 'true'.

 

But I might have gone a bit off topic. I think we agree that the situation is not ideal and I'm really grateful for the enhancement request. Furthermore there are multiple workarounds for the mean time

Badge +3

Hello @thijsknapen​ 

There currently isn't an XQuery function in FME to determine if an attribute is null or not. I have filed this request as an enhancement and will let you know once it has been implemented.

Our development team did mention it is possible to use the fme:get-json-attribute()

XQuery function as it does have special handling for null attributes. The downside is using this function will cause warnings and errors in the log since the attribute does not contain valid JSON which is not ideal. 

<dummyXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <a>value_a</a>
    {
        if ( not(fme:has-attribute("b")) )
        then ()
        else if ( not(fme:get-attribute("b") = "") )
        then (<b>{fme:get-attribute("b")}</b>)
        else if (xs:string(fme:get-json-attribute("b")) = "null")
        then (<b xsi:nil="true" nilReason="unknown"/>)
        else if ( fme:get-attribute("b") = "")
        then (<b/>)
        else ()
    }
    <c>value_c</c>
</dummyXML>

I hope this information helps.

Hi @debbiatsafe​ ,

 

Is it maybe possible to share an update on the status of the enhancement request? Is it being considered/planned, etc? 

 

In the end I'm of course mostly interested in if, and if so when I can expect this enhancement to make it into a new version of FME, but I understand that it's difficult to provide an exact timeline for this.

Userlevel 3
Badge +17

Hi @debbiatsafe​ ,

 

Is it maybe possible to share an update on the status of the enhancement request? Is it being considered/planned, etc?

 

In the end I'm of course mostly interested in if, and if so when I can expect this enhancement to make it into a new version of FME, but I understand that it's difficult to provide an exact timeline for this.

Hello @thijsknapen​ 

Support for a new FME XQuery function that is able to distinguish between a null attribute value and an empty string is planned (tracked as FMEENGINE-76086). However, there is not an exact timeline for this addition yet. I hope this information helps!

Badge +3

Hi @debbiatsafe​ ,

 

Is it maybe possible to share an update on the status of the enhancement request? Is it being considered/planned, etc?

 

In the end I'm of course mostly interested in if, and if so when I can expect this enhancement to make it into a new version of FME, but I understand that it's difficult to provide an exact timeline for this.

Check, thanks for the update @debbiatsafe​ !

Good to hear that this is planned.

Reply