如何使用 xmllint 或 xmlstarlet 替换 XML 文件中的字段?

发布于 2025-01-10 10:07:29 字数 943 浏览 0 评论 0原文

我有以下 xml 文件:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aut="http://">
   <soapenv:Header>
      <aut:Session>
         <aut:IPAddress>127.0.0.1</aut:IPAddress>
         <aut:SessionToken>true</aut:SessionToken>
         <aut:ApplicationToken>861</aut:ApplicationToken>
      </aut:Session>
   </soapenv:Header>
   <soapenv:Body></soapenv:Body>
</soapenv:Envelope>

What is the best way to replacement true by false

这是我正在尝试的:

xmllint --shell file.xml << EOF
cd //*[local-name() = "Header"]/*[local-name() = "Session"]/text()/*[local-name() = "SessionToken"]/text()
set failed
save
EOF

当我尝试将 true 替换为 false 时,由于名称空间而遇到问题。

兄弟, 京东

I have the following xml file:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aut="http://">
   <soapenv:Header>
      <aut:Session>
         <aut:IPAddress>127.0.0.1</aut:IPAddress>
         <aut:SessionToken>true</aut:SessionToken>
         <aut:ApplicationToken>861</aut:ApplicationToken>
      </aut:Session>
   </soapenv:Header>
   <soapenv:Body></soapenv:Body>
</soapenv:Envelope>

What is the best way to replace <aut:SessionToken>true</aut:SessionToken> by
<aut:SessionToken>false</aut:SessionToken> ?

Here is what I'm trying:

xmllint --shell file.xml << EOF
cd //*[local-name() = "Header"]/*[local-name() = "Session"]/text()/*[local-name() = "SessionToken"]/text()
set failed
save
EOF

I'm having problems because of namespace when I try to replace true for false.

Br,
JD

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

留一抹残留的笑 2025-01-17 10:07:29

处理 SOAP 信封时,我不会使用 *[local-name() = "..."]
它忽略名称空间。相反,请使用显式名称空间绑定。

要切换布尔值,例如

xmlstarlet edit -N aut="http://" \
    --var T '//aut:Session/aut:SessionToken' \
    -u '$T' -x 'not($T)' file.xml 

-N 之前添加 -L / --inplace 以就地编辑文件。

读取其值:

xmlstarlet select -N aut="http://" \
    -t -v '//aut:Session/aut:SessionToken' -n file.xml

When dealing with a SOAP envelope I wouldn't use *[local-name() = "…"]
which ignores the namespace. Instead, use an explicit namespace binding.

To toggle the boolean, for example

xmlstarlet edit -N aut="http://" \
    --var T '//aut:Session/aut:SessionToken' \
    -u '$T' -x 'not($T)' file.xml 

Add -L / --inplace before -N to edit the file in-place.

To read its value:

xmlstarlet select -N aut="http://" \
    -t -v '//aut:Session/aut:SessionToken' -n file.xml
靖瑶 2025-01-17 10:07:29

你快到了。那里只有一个额外的 text() 元素。在 xmlstartlet 中,尝试

    xml ed -u '//*[local-name() = "Header"]/*[local-name() = "Session"] \
//*[local-name() = "SessionToken"]//text()' -v "false" yourfile.xml

You're almost there. You just have an extra text() element in there. In xmlstartlet, try

    xml ed -u '//*[local-name() = "Header"]/*[local-name() = "Session"] \
//*[local-name() = "SessionToken"]//text()' -v "false" yourfile.xml
梦情居士 2025-01-17 10:07:29

您使用 xmllint 的方法与正确的方法相距不远。只需添加命名空间处理并在 XPath 表达式中使用命名空间前缀。

setrootns
cd //soapenv:Header/aut:Session/aut:SessionToken
set failed
save

作为单行:

echo -e "setrootns\n cd //soapenv:Header/aut:Session/aut:SessionToken\n set failed\n save\n bye" | xmllint --shell test.xml

Your approach with xmllint is not far from correct. Just needs to add namespace handling and use namespace prefixes in XPath expression.

setrootns
cd //soapenv:Header/aut:Session/aut:SessionToken
set failed
save

As a one-liner:

echo -e "setrootns\n cd //soapenv:Header/aut:Session/aut:SessionToken\n set failed\n save\n bye" | xmllint --shell test.xml
妄想挽回 2025-01-17 10:07:29

操作方法:调试 XML 结构并替换节点的值

由于 Google 可能会引导其他人必须使用不同的结构和节点更改自己的 XML 文件,因此找到正确的语法来更改值可能会很困难。

Sidenode:尽管 xmlstarlet 可能是替换 XML 文件中的值的更好工具,大多数 Unices 都预装了 xmllint

因此,以下实践展示了如何在交互模式(即调试)下使用 xmllint 浏览任何 xml 文件,以找到应替换的 Node(即语法) 。

xmllint --shell file.xml        # starts xmllint in interactive mode
setrootns                       # see LMCs explanation
cat                             # shows the complete XML structure

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aut="http://">
   <soapenv:Header>
      <aut:Session>
         <aut:IPAddress>127.0.0.1</aut:IPAddress>
         <aut:SessionToken>true</aut:SessionToken>
         <aut:ApplicationToken>861</aut:ApplicationToken>
      </aut:Session>
   </soapenv:Header>
   <soapenv:Body></soapenv:Body>
</soapenv:Envelope>

现在,您可以通过 XML 树逐步走到所需的节点:

cd //soapenv:Envelope                               # change to the first level
soapenv:Envelope >                                  # the prompt changes on success
cd //soapenv:Envelope/soapenv:Header/aut:Session
aut:Session > cat                                   # appropriate prompt change

<aut:Session>
     <aut:IPAddress>127.0.0.1</aut:IPAddress>
     <aut:SessionToken>true</aut:SessionToken>
     <aut:ApplicationToken>861</aut:ApplicationToken>
</aut:Session>

直接显示特定节点/路径的结构和值(无需事先 cd):

cat //soapenv:Envelope/soapenv:Header/aut:Session

<aut:Session>
     <aut:IPAddress>127.0.0.1</aut:IPAddress>
     <aut:SessionToken>true</aut:SessionToken>
     <aut:ApplicationToken>861</aut:ApplicationToken>
 </aut:Session>

记住不要有尾部斜杠在路径末尾,因为它找不到节点:

cat //soapenv:Envelope/soapenv:Header/aut:Session/    # trailing slash throws an error

XPath error : Invalid expression
//soapenv:Envelope/soapenv:Header/aut:Session/
                                             ^
//soapenv:Envelope/soapenv:Header/aut:Session: no such node

假设我们想更改 IP 地址,最好先检查正确的路径:

cat //soapenv:Envelope/soapenv:Header/aut:Session/aut:IPAddress

<aut:IPAddress>127.0.0.1</aut:IPAddress>

或者只是获取节点的值:

cat //soapenv:Envelope/soapenv:Header/aut:Session/aut:IPAddress/text()

127.0.0.1

首先保存原始文件作为 backup.xml,然后应用更改 file.xml,保存并保留 xmllint:

 cd //soapenv:Envelope/soapenv:Header/aut:Session/aut:IPAddress
 aut:IPAddress > cat text()         # alternative way to check the value
 127.0.0.1
 aut:IPAddress > save backup.xml    # create backup file
 aut:IPAddress > set 1.1.1.1        # change the value
 aut:IPAddress > cat text()         # crosscheck the changed value
 1.1.1.1
 aut:IPAddress > save               # save changes to file.xml
 aut:IPAddress > quit

在交互模式下 help 将显示有关命令的更多详细信息。 xmllint#Shell 部分> 也可能是一个很好的资源。

一旦确定了节点的正确路径(应该更改),您就可以参考更高效的 one-liner< /a> 正如 @LMC 所提到的,用于动态更改 XML 文件。

Howto: Debugging the XML structure and replacing values for a node

As Google might lead someone else here who has to alter his own XML file with a different structure and nodes, it could be arduous finding the proper syntax in order to change values.

Sidenode: eventough xmlstarlet might be the better tool for replacing values in XML files, most Unices have xmllint pre-installed.

Thus, the following practice shows how to navigate with xmllint in interactive mode (i. e. debug) through any xml file in order to find the Node (i.e syntax) which should be replaced.

xmllint --shell file.xml        # starts xmllint in interactive mode
setrootns                       # see LMCs explanation
cat                             # shows the complete XML structure

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aut="http://">
   <soapenv:Header>
      <aut:Session>
         <aut:IPAddress>127.0.0.1</aut:IPAddress>
         <aut:SessionToken>true</aut:SessionToken>
         <aut:ApplicationToken>861</aut:ApplicationToken>
      </aut:Session>
   </soapenv:Header>
   <soapenv:Body></soapenv:Body>
</soapenv:Envelope>

Now you can walk step by step to the desired node through the XML tree :

cd //soapenv:Envelope                               # change to the first level
soapenv:Envelope >                                  # the prompt changes on success
cd //soapenv:Envelope/soapenv:Header/aut:Session
aut:Session > cat                                   # appropriate prompt change

<aut:Session>
     <aut:IPAddress>127.0.0.1</aut:IPAddress>
     <aut:SessionToken>true</aut:SessionToken>
     <aut:ApplicationToken>861</aut:ApplicationToken>
</aut:Session>

Show directly the structure and values for a certain node/path (without prior cd):

cat //soapenv:Envelope/soapenv:Header/aut:Session

<aut:Session>
     <aut:IPAddress>127.0.0.1</aut:IPAddress>
     <aut:SessionToken>true</aut:SessionToken>
     <aut:ApplicationToken>861</aut:ApplicationToken>
 </aut:Session>

Bear in mind to not have a trailing slash at the end of the path as it won't find the node:

cat //soapenv:Envelope/soapenv:Header/aut:Session/    # trailing slash throws an error

XPath error : Invalid expression
//soapenv:Envelope/soapenv:Header/aut:Session/
                                             ^
//soapenv:Envelope/soapenv:Header/aut:Session: no such node

Assuming we would like to change the IP address, its a good idea to check first the proper path:

cat //soapenv:Envelope/soapenv:Header/aut:Session/aut:IPAddress

<aut:IPAddress>127.0.0.1</aut:IPAddress>

Or just get the value of the node:

cat //soapenv:Envelope/soapenv:Header/aut:Session/aut:IPAddress/text()

127.0.0.1

Save first the original file as backup.xml, then apply changes to file.xml, save it and leave xmllint:

 cd //soapenv:Envelope/soapenv:Header/aut:Session/aut:IPAddress
 aut:IPAddress > cat text()         # alternative way to check the value
 127.0.0.1
 aut:IPAddress > save backup.xml    # create backup file
 aut:IPAddress > set 1.1.1.1        # change the value
 aut:IPAddress > cat text()         # crosscheck the changed value
 1.1.1.1
 aut:IPAddress > save               # save changes to file.xml
 aut:IPAddress > quit

In interactive mode help will show further details about commands. The section #Shell at xmllint might also be a good resource.

As soon as the proper path for the node (which should be changed) has been identified, you can refer to the more efficient one-liner as mentioned by @LMC to change XML files on the fly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文