You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用xmlstarlet添加XML节点时格式异常,求格式保持方案

XMLStarlet 修改XML后保留原有属性换行格式问题

原始XML文件

<profile>
  <person name="user1" age="x years" 
  job="role1">
  </person> 
  <person name="user2" age="x years" 
  job="role1">
  </person>
</profile>

当前执行命令后的输出

<profile>
  <person name="user1" age="x years" job="role1">
  </person>
  <person name="user2" age="y years" job="role1">
  </person>
  <person name="user3" age="z years" job="role1">
  </person>
</profile>

期望的输出格式

<profile>
  <person name="user1" age="x years" 
  job="role1">
  </person>
  <person name="user2" age="y years" 
  job="role1">
  </person>
  <person name="user3" age="z years" 
  job="role1">
  </person>
</profile>

使用的命令

xmlstarlet edit -s '/profile' -t elem -n 'newnode' -s '//newnode' -t text -n '' -v "" \
    -i //newnode -t attr -n "name" -v "user3" \
    -i //newnode -t attr -n "age" -v "z years" \
    -i //newnode -t attr -n "job" -v "role1" \
    -r //newnode -v person \
    file.xml

解决方法

方法1:启用保留原始格式选项

XMLStarlet默认会重新格式化XML,用--pf参数可以让它尽量保留原有文档的排版:

xmlstarlet edit --pf -s '/profile' -t elem -n 'newnode' -s '//newnode' -t text -n '' -v "" \
    -i //newnode -t attr -n "name" -v "user3" \
    -i //newnode -t attr -n "age" -v "z years" \
    -i //newnode -t attr -n "job" -v "role1" \
    -r //newnode -v person \
    file.xml

这个参数会保留原有节点的换行格式,新节点的属性排版也会尽量匹配原始风格。

方法2:直接插入原始XML片段

如果--pf效果不理想,可以直接插入符合格式要求的原始XML代码,完全绕过XMLStarlet的自动格式化:

xmlstarlet edit -s '/profile' -t raw -n '' -v '  <person name="user3" age="z years" 
  job="role1">
  </person>' file.xml

如果需要直接修改原文件,加上-L参数即可。

方法3:自定义XSLT格式化规则

创建一个XSLT样式表format.xsl,精准控制属性的换行位置:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="person">
    <xsl:text>&#xA;  </xsl:text>
    <person>
      <xsl:attribute name="name">
        <xsl:value-of select="@name"/>
      </xsl:attribute>
      <xsl:text>&#xA;  </xsl:text>
      <xsl:attribute name="age">
        <xsl:value-of select="@age"/>
      </xsl:attribute>
      <xsl:text>&#xA;  </xsl:text>
      <xsl:attribute name="job">
        <xsl:value-of select="@job"/>
      </xsl:attribute>
      <xsl:text>&#xA;  </xsl:text>
    </person>
  </xsl:template>

  <xsl:template match="/profile">
    <profile>
      <xsl:apply-templates select="person"/>
    </profile>
  </xsl:template>
</xsl:stylesheet>

先执行原修改命令,再用XSLT格式化输出:

xmlstarlet edit -s '/profile' -t elem -n 'newnode' -s '//newnode' -t text -n '' -v "" \
    -i //newnode -t attr -n "name" -v "user3" \
    -i //newnode -t attr -n "age" -v "z years" \
    -i //newnode -t attr -n "job" -v "role1" \
    -r //newnode -v person \
    file.xml | xmlstarlet tr format.xsl

内容的提问来源于stack exchange,提问作者Vanaan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:35:42