Reputation: 41
While doing the xquery transformation I came across the condition where in I want to remove the empty attribute of an element.
Example:
<product
name="{data($cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product/@name)}"
a="{data($cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product/@a)}"
b="{data($cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product/@b)}"
c="{data($cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product/@c)}"
/>
on testing got the output as <Product name="abc" a="xyz" b="def" c=""/>
Here I want to remove the attribute having null value i.e c. I tried many things but couldnt resolve it. Anyone having any idea how to do it?
Upvotes: 0
Views: 3826
Reputation: 3517
You can also use a mix of direct constructors and computed constructors, sometimes this syntax feels more natural. As long as you place your computed attribute constructors (for your optional attributes) as the first thing inside your direct element constructor, you will achieve your requirement.
For example:
<product mandatory="foo">
{
if($some-condition)then
attribute optional { "bar" }
else()
}
</product>
When $some-condition is true()
it would result in:
<product mandatory="foo" optional="bar">
</product>
and when $some-condition is false()
it would result in:
<product mandatory="foo">
</product>
So for your supplied example, you could do this:
<product name="{data($cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product/@name)}"
a="{(data($cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product/@a)) }"
b="{(data($cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product/@b))}">
{
if(data($cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product/@c))then
attribute c {
data($cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product/@c)
}
else()
}
</product>
However, it seems to me that you are copying attributes from the source node to the destination node, and that you really just want to copy specific attributes from the source that are available. If that is the case, then it is much simpler to just do this:
let $product := $cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product
return
<product>
{
$product/(@name | @a | @b | @c)
}
</product>
If you want to copy all available attributes, just use $product/@*
.
Upvotes: 1
Reputation: 38682
If you need to construct the attributes, test if it is not the empty string. I used computed element constructors and a let
clause for readabilty, but the code is doing the same like you did, adding the attribute check for @c
.
element Product {
let $product = $cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product
return
attribute name { $product/@name },
attribute a {$product/@a },
attribute b {$product/@b },
if ($product/@c != '') then attribute c {$product/@c } else ()
}
If the product does not exist in the input data, you'd better go for just adding the original attributes instead of constructing them:
element product {
let $product = $cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product
return $product/@name, $product/@a, $product/@b, $product/@c
}
Upvotes: 2