我有一个XML文件。只是阅读,我可以告诉你很兴奋。
现在我想完全删除一些标签:
<qwerty option=1>
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
这是个大文件。如何删除所有标记nmo
和blue
,包括其内容?在Emacs中,或者我的mac可以使用的任何其他内容。
答案 0 :(得分:4)
Emacs具有用于导航符号表达式或“sexps”的命令。在xml-mode
中,sexp导航命令适用于标记。您可以导航到开头<
,按 CMf (forward-sexp
)导航到标记的末尾,或按 CMk ({{ 1}})杀死它。变量kill-sexp
控制您是在开始标记的末尾(默认值)还是结束标记的结尾。我更喜欢后者。
要删除这些标记,首先使用 M-x customize-variable nxml-sexp-element-flag 设置nxml-sexp-element-flag
。接下来,搜索您要杀死的标记,将该点移动到开头nxml-sexp-element-flag
并按 C-M-k 。将此全部包装在一个宏中,并重复整个文件,直到搜索失败。
答案 1 :(得分:3)
我假设您的xml文件格式正确。而且我还假设与您的示例相反,您的“真实”数据比每行一个标记稍微复杂一些(除了根目录之外)。否则,我们是否同意删除包含给定标记的行这么简单?
这是一个可以解决问题的函数的命题:
(defun my-remove-tag (tag)
(save-excursion
(let ((case-fold-search nil))
(while (search-forward-regexp (concat "<" tag "[^\\>]*>"))
(delete-region
(match-beginning 0)
(search-forward (concat "</" tag ">")))))))
调用此功能,您可以查找nmo
,blue
或qwerty
标记,如下所示:
(my-remove-tag "nmo")
(my-remove-tag "qwerty")
理由是寻找一个开始标记然后寻找结束标记,并删除中间的所有内容。标记的属性可以在中间,并且此函数处理包含属性的开始标记。
一旦功能完成,将禁用并恢复区分大小写。此外,Emacs Point将使用通常的宏恢复:save-excusion
。
我删除了外部let。无需手动恢复case-fold-search值,let绑定只会影响全局值,它通过“unhadowing”恢复。
答案 2 :(得分:3)
我认为更通用的方法是使用更多面向XML的工具,比如XSL(T)(不要害怕,没人喜欢),但如果你必须工作它会派上用场使用XML(不要害怕,也没有人喜欢)。
所以,我们走了:
这是你的XSL文件(它复制原始XML中的所有内容,并用空行替换你想要删除的节点。最后,它打印出来,使它看起来更漂亮,然后如果你用它替换它一个正则表达式。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Copy everything -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- Find any node named nmo or blue and replace it with nothing -->
<xsl:template match="nmo | blue"/>
</xsl:stylesheet>
这是我以前测试的例子:
<?xml version="1.0" encoding="utf-8"?>
<nodes>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
<nodes>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
</nodes>
<nodes>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
<other node=""/>
<nodes>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
</nodes>
</nodes>
</nodes>
这是我收到的输出:
<?xml version="1.0"?>
<nodes>
<qwerty option="1"/>
<nodes>
<qwerty option="1"/>
</nodes>
<nodes>
<qwerty option="1"/>
<other node=""/>
<nodes>
<qwerty option="1"/>
<qwerty option="1"/>
<qwerty option="1"/>
</nodes>
</nodes>
</nodes>
注意它是如何关闭qwerty
节点的。
获取此命令的命令行如下:
xsltproc ./remove-nodes.xsl ./nodes-to-be-removed.xml > result.xml
你可以从Emacs的shell运行它,或者使用任何Emacs的函数来调用它/用它创建一个进程,依此类推。 man xsltproc
了解更多信息 - 它的用法非常基本。它安装在我的Fedora上,但我想可以认为,由于全世界普遍存在XML,它可能已经安装在Mac上,或者必须以某种方式安装。