我使用xmlstarlet el -v来显示xml文件的结构,包括所有属性和值.我想将其输出转换为某种键值对,即每个属性的值在一个单独的行上(包括XPath);每一行必须是唯一的.
目前的结果:
topRoot/topSystem/commSvcEp/commSyslog[@descr='Syslog Service' and @name='syslog' and @policyOwner='local' and @severity='critical'] topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[@adminState='disabled' and @forwardingFacility='local7' and @hostname='none' and @name='secondary' and @severity='critical'] topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[@adminState='disabled' and @forwardingFacility='local7' and @hostname='none' and @name='tertiary' and @severity='critical'] topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[@adminState='disabled' and @forwardingFacility='local7' and @hostname='none' and @name='primary' and @severity='critical']
期望的结果(可能是类似的;指数只是一个想法):
topRoot/topSystem/commSvcEp/commSyslog@descr='Syslog Service' topRoot/topSystem/commSvcEp/commSyslog@name='syslog' topRoot/topSystem/commSvcEp/commSyslog@policyOwner='local' topRoot/topSystem/commSvcEp/commSyslog@severity='critical' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[0]@adminState='disabled' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[0]@forwardingFacility='local7' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[0]@hostname='none' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[0]@name='secondary' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[0]@severity='critical' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[1]@adminState='disabled' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[1]@forwardingFacility='local7' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[1]@hostname='none' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[1]@name='tertiary' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[1]@severity='critical' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[2]@adminState='disabled' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[2]@forwardingFacility='local7' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[2]@hostname='none' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[2]@name='primary' topRoot/topSystem/commSvcEp/commSyslog/commSyslogClient[2]@severity='critical'
我想要完成的是能够在两个这样的文件上运行diff或使用grep来过滤匹配的模式.我确信有一种方法可以创建这样的输出,而不使用sed,awk或其他任何东西,但xmlstarlet本身.
我几乎是关于xmlstarlet和整个xml世界的新手(不仅因为它因为它的复杂性和解析开销等而不喜欢xml),所以我非常感谢你的帮助.谢谢!
由于您已经在使用xmlstarlet,因此您也可以使用XSLT.
XSLT 1.0(可以使用tr命令使用xmlstarlet运行)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:strip-space elements="*"/> <xsl:param name="sep" select="'.'"/> <xsl:template match="text()"/> <xsl:template match="*"> <xsl:variable name="path"> <xsl:for-each select="ancestor-or-self::*"> <xsl:variable name="predicate"> <xsl:call-template name="genPredicate"/> </xsl:variable> <xsl:if test="ancestor::*"> <xsl:value-of select="$sep"/> </xsl:if> <xsl:value-of select="concat(local-name(),$predicate)"/> </xsl:for-each> </xsl:variable> <xsl:for-each select="@*"> <xsl:value-of select="concat($path,$sep,name(),'=',.)"/> <xsl:text>
</xsl:text> </xsl:for-each> <xsl:if test="not(@*)"> <xsl:text>
</xsl:text> </xsl:if> <xsl:apply-templates select="node()"/> </xsl:template> <xsl:template name="genPredicate"> <xsl:if test="preceding-sibling::*[local-name()=local-name(current())] or following-sibling::*[local-name()=local-name(current())]"> <xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/> </xsl:if> </xsl:template> </xsl:stylesheet>
注意:有一个名为sep的参数,因此您可以从命令行更改分隔符(使用-p sep =“/”或您想要的任何分隔符).它目前设置为您首选的“.”.
产量
commSyslog.descr=Syslog Service commSyslog.name=syslog commSyslog.policyOwner=local commSyslog.severity=critical commSyslog.commSyslogClient[1].adminState=disabled commSyslog.commSyslogClient[1].forwardingFacility=local7 commSyslog.commSyslogClient[1].hostname=none commSyslog.commSyslogClient[1].name=secondary commSyslog.commSyslogClient[1].severity=critical commSyslog.commSyslogClient[2].adminState=disabled commSyslog.commSyslogClient[2].forwardingFacility=local7 commSyslog.commSyslogClient[2].hostname=none commSyslog.commSyslogClient[2].name=tertiary commSyslog.commSyslogClient[2].severity=critical commSyslog.commSyslogClient[3].adminState=disabled commSyslog.commSyslogClient[3].forwardingFacility=local7 commSyslog.commSyslogClient[3].hostname=none commSyslog.commSyslogClient[3].name=primary commSyslog.commSyslogClient[3].severity=critical commSyslog.commSyslogMonitor.adminState=disabled commSyslog.commSyslogMonitor.descr= commSyslog.commSyslogMonitor.name= commSyslog.commSyslogMonitor.severity=critical commSyslog.commSyslogConsole.adminState=disabled commSyslog.commSyslogConsole.descr= commSyslog.commSyslogConsole.name= commSyslog.commSyslogConsole.severity=critical commSyslog.commSyslogSource.audits=disabled commSyslog.commSyslogSource.descr= commSyslog.commSyslogSource.events=disabled commSyslog.commSyslogSource.faults=enabled commSyslog.commSyslogSource.name= commSyslog.commSyslogFile.adminState=enabled commSyslog.commSyslogFile.descr= commSyslog.commSyslogFile.name=messages commSyslog.commSyslogFile.severity=critical commSyslog.commSyslogFile.size=4194304