xidel:在 shell 中使用 XQuery 删除节点

问题描述 投票:0回答:3

示例 XML:

<outerTag>
  <innerElement>
    <Id>1234</Id>
    <fName>Kim</fName>
    <lName>Scott</lName>
<customData1>Value1</customData1>
<customData2>Value2</customData2>
    <position>North<position>
    <title/>
  </innerElement>
  <innerElement>
    <Id>5678</Id>
    <fName>Brian</fName>
    <lName>Davis</lName>
<customData3>value3</customData3>
<customData4>value4</customData4>
<customData5>value5</customData5>
    <position>South<position>
    <title/>
  </innerElement>
</outerTag>

预期产出:

<outerTag>
  <innerElement>
    <Id>1234</Id>
    <fName>Kim</fName>
    <lName>Scott</lName>
    <customData1>Value1</customData1>
    <customData2>Value2</customData2>
    <position>North<position><title/></position>
  </position>
  </innerElement>
</outerTag>

我知道我可以只使用好的选择

Xpath
来做这个把戏,但我试图弄清楚如何使用
delete
xidel
XQuery

我从this试过:

xidel --xml -e '
    let $element := //innerElement[not(Id["1234"])]
    declare function local:process-xml ($element) {
        $element update delete node
    }
' file.xml

我得到:

An unhandled exception occurred at $00000000006174CA:
ERangeError: Range check error
  $00000000006174CA
  $000000000061782C
  $0000000000629536
  $000000000062E638
  $000000000055C12B

$ xidel --xquery '
    let $element := //innerElement[./not(Id["1234"])]
    declare function local:process-xml ($element) {
        $element update delete node                                                  
    }
' file.xml

我得到同样的错误。

或者使用 纯 XQuery

$ xidel --xml --xquery '
    let $input := /outerTag
    modify delete node $input/innerElement[Id ne "1234"]
    return $input
' file.xml

我得到错误:

Error:
err:XPST0003: Missing whitespace or symbol
in line 2 column 5
    modify delete node $input/innerElement[Id ne "1234"]
    ^^^^  error occurs around here

令人沮丧

xidel
无法处理这种纯粹的
XQuery
解决方案。

xml shell xquery xidel
3个回答
1
投票

这里是一个纯 XQuery 解决方案,在 BaseX 10.5 中测试

XQuery

declare context item := document {
<outerTag>
    <innerElement>
        <Id>1234</Id>
        <fName>Kim</fName>
        <lName>Scott</lName>
        <customData1>Value1</customData1>
        <customData2>Value2</customData2>
        <position>North</position>
        <title/>
    </innerElement>
    <innerElement>
        <Id>5678</Id>
        <fName>Brian</fName>
        <lName>Davis</lName>
        <customData3>value3</customData3>
        <customData4>value4</customData4>
        <customData5>value5</customData5>
        <position>South</position>
        <title/>
    </innerElement>
</outerTag>
};

copy $input := .
modify delete node $input/outerTag/innerElement[Id ne "1234"]
return $input

输出

<outerTag>
  <innerElement>
    <Id>1234</Id>
    <fName>Kim</fName>
    <lName>Scott</lName>
    <customData1>Value1</customData1>
    <customData2>Value2</customData2>
    <position>North</position>
    <title/>
  </innerElement>
</outerTag>

XQuery #2

以文件名作为参数

declare base-uri 'e:\Temp\';
declare option db:stripws "true";

copy $input := doc("input.xml")
modify delete node $input/outerTag/innerElement[Id ne "1234"]
return $input

Linux 版本

copy $input := doc("/tmp/file.xml")
modify delete node $input/outerTag/innerElement[Id ne "1234"]
return $input

1
投票

Xidel 不支持“XQuery 更新”。参见邮件列表讨论
附带说明:虽然可以使用 Xidel 编辑 XML,但它的目标不是成为一个完全成熟的编辑器。 Benito 创建 Xidel 的初衷是作为提取器。

可以使用

transform()
,但是wiki已经很久没有更新了,目前这个功能已经被弃用了:

$ xidel -s file.xml -e '
  transform(
    /,
    function($x){
      if (name($x)="innerElement" and $x/Id="5678")
      then ()
      else $x
    }
  )
' --output-node-format=xml --output-node-indent
pxp:transform(..) is deprecated, use x:transform-nodes(..)
<outerTag>
  <innerElement>
    <Id>1234</Id>
    <fName>Kim</fName>
    <lName>Scott</lName>
    <customData1>Value1</customData1>
    <customData2>Value2</customData2>
    <position>North</position>
    <title/>
  </innerElement>
</outerTag>

相反,我会推荐

x:replace-nodes()
,它更容易使用:

$ xidel -s file.xml -e 'x:replace-nodes(//innerElement[Id="5678"],())' \
  --output-node-format=xml --output-node-indent

0
投票

来自

xidel
doc的尝试示例:

$ xidel --xml -e '
    let $delete := //innerElement[not(Id="1234")]
    return transform(/, function($e){ $e[not($delete[$e is .])]})
'  file.xml

看起来有点复杂

编辑:此语法现已弃用。

如果这可以简化或使用普通的纯XQuery作为这个答案.

将接受另一个答案
© www.soinside.com 2019 - 2024. All rights reserved.