【问题标题】:strip comments from xml file and pretty-print it从 xml 文件中删除注释并漂亮地打印它
【发布时间】:2010-11-30 16:26:03
【问题描述】:

我有一个包含很多 cmets 的巨大 xml 文件。

去除所有 cmets 并从 linux 命令行很好地格式化 xml 的“最佳方法”是什么?

【问题讨论】:

标签: xml bash sh


【解决方案1】:

你可以用整洁

$ tidy -quiet -asxml -xml -indent -wrap 1024 --hide-comments 1 tomcat-users.xml
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <user username="qwerty" password="ytrewq" roles="manager-gui" />
</tomcat-users>

【讨论】:

  • 在参数中添加“-modify”以更改文件。 (你做了备份,对吧?)
  • 当心! tidy 中有一个错误会删除 XML 中的空格,因此请谨慎使用上述答案。开放错误链接:github.com/htacg/tidy-html5/issues/818
【解决方案2】:

通过identity transform XSLT 运行您的XML,并为cmets 提供一个空模板。

除了 cmets 之外的所有 XML 内容都将传递到输出。

为了侄女格式化输出,设置输出@indent="yes":

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<!--Match on Attributes, Elements, text nodes, and Processing Instructions-->
<xsl:template match="@*| * | text() | processing-instruction()">
   <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
   </xsl:copy>
</xsl:template>

<!--Empty template prevents comments from being copied into the output -->
<xsl:template match="comment()"/>

</xsl:stylesheet>

【讨论】:

  • 我和&lt;xsl:template match="@*| * | text() | processing-instruction() | comment()[contains(., 'licence')]"&gt;一起使用
【解决方案3】:

您可能想查看xmllint 工具。它有几个选项(其中一个--format 会打印得很漂亮),但我不知道如何使用这个工具删除 cmets。

另外,请查看XMLStarlet,这是一组命令行工具,可以用 xml 完成任何您想做的事情。然后做:

xml c14n --without-comments # XML file canonicalization w/o comments

EDIT:OP 最终使用了这一行:

xmlstarlet c14n --without-comments old.xml > new.xml

【讨论】:

  • xmllint 是 libxml2 的命令行接口,libxml2 是一个具有多种语言绑定的库。例如。我在 Perl 中使用 XML::LibXML。
  • 我曾经使用过:xmlstarlet c14n --without-cmets old.xml > new.xml
【解决方案4】:

为了整理像 Tomcat 的 server.xml 这样简单的东西,我使用

sed 's/<!--/\x0<!--/g;s/-->/-->\x0/g' | grep -zv '^<!--' | tr -d '\0' | grep -v "^\s*$"

function tidy() {
 echo "$( cat $1 | sed 's/<!--/\x0<!--/g;s/-->/-->\x0/g' | grep -zv '^<!--' | tr -d '\0' | grep -v "^\s*$")"
}

tidy server.xml

... 将打印没有 cmets 的 xml。

注意:虽然它在简单的事情上工作得相当好,但在某些 CDATA 块和其他一些情况下它会失败。仅将它用于不需要也永远不需要在任何地方转义单个 &lt;----&gt; 的受控 xml 脚本!

首先 sed 用 0x0 字符标记注释​​的开始和结束,然后 grep 和 -z 将 0x0 视为唯一的行分隔符,搜索以注释开头的行,它的 -v 反转过滤器,只留下有意义的行。最后,tr -d\0` 删除了所有这些 0x0,为了完善它,另一个 grep 删除了空行:瞧。

【讨论】:

    【解决方案5】:

    最好的方法是使用 XML 解析器来正确处理所有晦涩的极端情况。但是,如果您需要快速而肮脏的东西,有多种short solutions using Perl regexes 可能就足够了。

    【讨论】:

    • @reinierpost:我理解为什么这个答案看起来令人反感。但是,如果这是一次性的,并且您知道您的 cmets 是评论规范的一个受严格约束的子集,那么正则表达式解决方案有什么问题?我同意解析工具更可取(并且是最佳答案),但我确实认为这在某些特定情况下是有效的替代方案(例如简单测试或只读系统上的凌晨 2 点危机标注),并且非常方便.
    • 有了有效的 XML,因此只有 cmets 是 cmets,我认为 XML 解析器更好。但是,如果您使用包含条件的 cmets 处理 HTML(例如 Internet Explorer),那么正则表达式可能是您最好的选择。
    猜你喜欢
    • 2010-09-05
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 1970-01-01
    相关资源
    最近更新 更多