【问题标题】:how to remove empty attribute from xquery如何从xquery中删除空属性
【发布时间】:2014-02-10 10:48:54
【问题描述】:

在进行 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)}"
/>

在测试中得到的输出为&lt;Product name="abc" a="xyz" b="def" c=""/&gt;

在这里我想删除具有空值的属性,即 c。 我尝试了很多事情,但无法解决它。 有人知道怎么做吗?

【问题讨论】:

    标签: xquery osb


    【解决方案1】:

    如果需要构造属性,请测试是否为空字符串。我使用了计算元素构造函数和let 子句以提高可读性,但代码的执行方式与您相同,为@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
    }
    

    【讨论】:

    • 更通用的解决方案是通过这样的函数运行元素:declare function local:remove-empty-attributes($element as element()) as element() { element { node-name($element)} { $element/@*[string(.)], for $child in $element/node( ) return if ($child instance of element()) then local:remove-empty-attributes($child) else $child } };
    • 如果您支持 XQuery 更新:delete nodes //@*[not(data())],可能包含在 modify/copy 语句中。
    【解决方案2】:

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

    例如:

    <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/@*

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-26
      • 1970-01-01
      • 2017-05-18
      • 2011-12-22
      • 1970-01-01
      • 1970-01-01
      • 2014-07-18
      相关资源
      最近更新 更多