以特定方式解析.xml文件

以特定方式解析.xml文件

我有以下 .xml,并且想要特定的输出:

<ContactPerson>
<GivenName>John</GivenName>
<FamilyName>Wayne</FamilyName>
<PhoneFixList>
<PhoneFix>78787878</PhoneFix>
</PhoneFixList>
<EmailList>
<Email>[email protected]</Email>
</EmailList>
</ContactPerson>

<ContactPerson>
<GivenName>James</GivenName>
<FamilyName>Stewart</FamilyName>
<PhoneFixList>
<PhoneFix>90909090</PhoneFix>
</PhoneFixList>
<EmailList>
<Email>[email protected]</Email>
</EmailList>
</ContactPerson>

输出:

John Wayne  78787878  [email protected]
James Stewart  90909090  [email protected]

在某些情况下,我有两个以上,<ContactPerson>所以我很高兴有一个很好的循环来解决这个问题。我尝试用 for 循环解决问题,但总是得到结果:

John Wayne  78787878  [email protected]
John Wayne  78787878  [email protected]

答案1

假设以下(修改后的)XML:

<?xml version="1.0"?>
<root>
  <ContactPerson>
    <GivenName>John</GivenName>
    <FamilyName>Wayne</FamilyName>
    <PhoneFixList>
      <PhoneFix>78787878</PhoneFix>
    </PhoneFixList>
    <EmailList>
      <Email>[email protected]</Email>
    </EmailList>
  </ContactPerson>
  <ContactPerson>
    <GivenName>James</GivenName>
    <FamilyName>Stewart</FamilyName>
    <PhoneFixList>
      <PhoneFix>90909090</PhoneFix>
    </PhoneFixList>
    <EmailList>
      <Email>[email protected]</Email>
    </EmailList>
  </ContactPerson>
</root>

XML小星 调用

xml sel -t -m '//ContactPerson' -v 'concat(GivenName, " ", FamilyName, " ", PhoneFixList/PhoneFix, " ", EmailList/Email)' -nl file.xml

产生

John Wayne 78787878 [email protected]
James Stewart 90909090 [email protected]

XMLStarlet 的调用包含对所有ContactPerson节点的隐式循环,并且对于每个节点,特定字段被连接以产生正确的输出。最后-nl的 导致打印换行符。

答案2

使用xml2(以及支持引号的 shell $'...'):

{ echo "<r>"; cat file.xml; echo "</r>"; } |
  | xml2 | 2csv -d $'\t' ContactPerson GivenName FamilyName EmailList/Email

(对于ContactPerson具有多个电子邮件地址的 s,返回最后一个)

答案3

如果您同意使用第二个文件来处理此问题,则可以创建一个 XSLT 文件并使用它来转换您的 XML 文件xsltproc

电话.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ContactPerson">
  <xsl:value-of select="GivenName"/><xsl:text> </xsl:text><xsl:value-of select="FamilyName"/>
  <xsl:for-each select="PhoneFixList/PhoneFix">
    <xsl:text> </xsl:text><xsl:value-of select="."/>
  </xsl:for-each>
  <xsl:for-each select="EmailList/Email">
    <xsl:text> </xsl:text><xsl:value-of select="."/>
  </xsl:for-each>
  <xsl:text>&#xA;</xsl:text>
</xsl:template>
</xsl:stylesheet>

然后转换文件(使用 @Kusalananda 的 XML as phones.xml):

$ xsltproc phones.xsl phones.xml
John Wayne 78787878 [email protected]
James Stewart 90909090 [email protected]

使用 XSLT 的优点是您可以循环重复元素、进行条件输出等等。如果您愿意进行一些学习和编程,那么它的功能非常强大。

相关内容