使用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>
 </xsl:text> <person> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:text>
 </xsl:text> <xsl:attribute name="age"> <xsl:value-of select="@age"/> </xsl:attribute> <xsl:text>
 </xsl:text> <xsl:attribute name="job"> <xsl:value-of select="@job"/> </xsl:attribute> <xsl:text>
 </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
相关产品推荐
相关产品推荐

