如何从xquery中删除空属性

时间:2014-02-10 10:48:55

标签: xquery osb

在进行xquery转换时,遇到了我想删除元素的空属性的情况。

示例:

<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将输出设为<Product name="abc" a="xyz" b="def" c=""/>

这里我想删除具有空值的属性,即c。 我尝试了很多东西,但无法解决它。 任何人都知道如何做到这一点?

2 个答案:

答案 0 :(得分:2)

如果需要构造属性,请测试它是否为空字符串。我使用了计算元素构造函数和let子句来实现readabilty,但是代码和你一样做了,添加了@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 ()
}

如果输入数据中不存在该产品,您最好只添加原始属性而不是构建它们:

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
}

答案 1 :(得分:1)

您还可以使用直接构造函数和计算构造函数的混合,有时这种语法感觉更自然。只要将计算出的属性构造函数(对于可选属性)作为直接元素构造函数中的第一个内容,就可以实现自己的要求。

例如:

<product mandatory="foo">
{
    if($some-condition)then
        attribute optional { "bar" }
    else()
} 
</product>

当$ some-condition为true()时,会导致:

<product mandatory="foo" optional="bar">
</product>

当$ some-condition为false()时,会导致:

<product mandatory="foo">
</product>

因此,对于您提供的示例,您可以这样做:

<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>

但是,在我看来,您正在将属性从源节点复制到目标节点,并且您真的只想从源中复制可用的特定属性。如果是这种情况,那么这样做要简单得多:

let $product := $cBRequestType1/ns0:BCAmessage/ns0:BCAservice/ns0:BCAservice-data/ns0:request/ns0:VerificationEnquiryRequest/ns0:product
return
    <product>
    {
        $product/(@name | @a | @b | @c)
    }
    </product>

如果要复制所有可用属性,只需使用$product/@*