Ant*_*sov 2 xml linux bash xmlstarlet
我有 RSS 提要,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>my feed</title>
<link rel="self" href="http://myhomesite.com/articles/feed/"/>
<updated>2019-11-04T12:45:00Z</updated>
<id>http://myhomesite.com/articles/feed/?dt=2019-11-04T12:45:00Z</id>
<entry>
<id>id0</id>
<link rel="alternate" type="text/html" href="https://yandex.ru/link123"/>
<author>
<name/>
</author>
<published>2019-11-04T12:45:00Z</published>
<updated>2019-11-04T12:45:00Z</updated>
<title type="html"><![CDATA[foo bar foo bar]]></title>
<content type="html"><![CDATA[]]></content>
</entry>
<entry>
<id>id2</id>
<link rel="alternate" type="text/html" href="https://myhomesite.com"/>
<author>
<name/>
</author>
<published>2019-11-04T09:45:00Z</published>
<updated>2019-11-04T09:45:00Z</updated>
<title type="html"><![CDATA[foo bar foo bar]]></title>
<content type="html"><![CDATA[]]></content>
</entry>
....
Run Code Online (Sandbox Code Playgroud)
我想删除link href !=/feed/entry处的所有节点 ( ) 。 http://myhomesite.com
如何使用 Bash 删除值从指定符号开始的 XML 节点?
Bash 功能本身不太适合解析 XML。
这个著名的Bash FAQ声明如下:
考虑使用 XML 特定的命令行工具,例如XMLStarlet。如果您尚未安装 XML Starlet,请参阅此处的下载信息。
使用 XML Starlet,您可以运行以下命令将所需的结果输出到终端:
xml ed -N x="http://www.w3.org/2005/Atom" -d '//x:entry[not(child::x:link[@href="https://myhomesite.com"])]' /path/to/file.rss
Run Code Online (Sandbox Code Playgroud)
注意:/path/to/file.rss上面显示的命令末尾的部分应替换为实际文件的真实路径名.rss。
解释:
上述命令的各个部分细分如下:
xml- 调用 XML Starlet 命令。
ed- 编辑/更新 XML 文档。
-N x="http://www.w3.org/2005/Atom"- 该-N选项将名称空间(即)绑定http://www.w3.org/2005/Atom到我们任意命名的前缀x。
-d- 删除匹配的节点。
'//x:entry[not(child::x:link[@href="https://myhomesite.com"])]'xpath表达式用于查找/匹配问题中指定的适当节点。
链接 href != 的所有节点 (/feed/entry)
http://myhomesite.com。
正如您所看到的,在 XPath 表达式中,我们在x元素节点名称前面添加前缀,即x:entry和x:link,以确保我们在正确的命名空间中寻址元素。
/path/to/file.rss- 源.rss文件的路径名。
要保存生成的 XML,您可以:
将选项添加--inplace到上述命令 - 这将.rss用所需的结果覆盖原始命令。例如:
xml ed --inplace -N x="http://www.w3.org/2005/Atom" -d '//x:entry[not(child::x:link[@href="https://myhomesite.com"])]' /path/to/file.rss
Run Code Online (Sandbox Code Playgroud)
或者,使用重定向运算符( >) 并指定保存输出的位置的路径名。例如,以下复合命令会将结果保存到新文件中:
xml ed -N x="http://www.w3.org/2005/Atom" -d '//x:entry[not(child::x:link[@href="https://myhomesite.com"])]' /path/to/file.rss > /path/to/results.rss
Run Code Online (Sandbox Code Playgroud)
注意:上述复合命令末尾/path/to/results.rss的 应该替换为要保存新文件的真实路径名。
local-name():鉴于您的示例源 XML (RSS) 不包含任何QName,因此也可以利用 XPath 的local-name()功能。这将不需要使用 XMLStarlet 的-N选项来绑定命名空间。例如:
xml ed -d '//*[local-name() = "entry" and not(child::*[local-name() = "link"][@href="https://myhomesite.com"])]' /path/to/file.rss
Run Code Online (Sandbox Code Playgroud)
重要提示:您可能xml需要替换本文中显示的所有示例命令中的前导部分xmlstarlet。例如:
xmlstarlet ed -N x="http://www.w3.org/2005/Atom" -d '//x:entry[not(child::x:link[@href="https://myhomesite.com"])]' /path/to/file.rss.
^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
编辑:
鉴于您的示例 XML,还可以对默认名称空间使用简化的语法,即_:使用x:. 通过使用下划线 ( _),您无需使用-N将名称空间绑定到前缀的选项。请参阅标题为 1.3 的部分。XMLStarlet 文档中的更方便的解决方案可获取有关此功能的更多信息。
例如:
xml ed -d '//_:entry[not(child::_:link[@href="https://myhomesite.com"])]' /path/to/file.rss
Run Code Online (Sandbox Code Playgroud)
为了进一步了解当源 XML 使用命名空间时如何使用 XMLStarlet,我建议您还阅读文档中的命名空间和默认命名空间。
编辑2:
OP的作者随后在评论中写道:
还有一个问题。条件
[not(child::_:link[@href="myhomesite.com"])]很严格。我想要像 start withmyhomesite.com但 URI 不重要,即myhomesite.com**anything**。这是可能的?[原文如此]像这样的东西..
xmlstarlet ed -N x="http://www.w3.org/2005/Atom" -d '//x:entry[not(child::x:link[matches(@href, '^https://myhomesite.com/' )]/@href)]' feed.rs
考虑将 Xpath 的starts-with()函数与前面给出的任一示例结合使用。例如:
使用-N选项 和starts-with():
xml ed -N x="http://www.w3.org/2005/Atom" -d '//x:entry[not(child::x:link[starts-with(@href, "https://myhomesite.com")])]' file.rss
Run Code Online (Sandbox Code Playgroud)
使用local-name()和starts-with():
xml ed -d '//*[local-name() = "entry" and not(child::*[local-name() = "link"][starts-with(@href, "https://myhomesite.com")])]' file.rss
Run Code Online (Sandbox Code Playgroud)
使用默认命名空间的简化语法,即下划线和starts-with():
xml ed -d '//_:entry[not(child::_:link[starts-with(@href, "https://myhomesite.com")])]' file.rss
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
973 次 |
| 最近记录: |