1

I have the following .xml and I want a specific output:

<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> 

Output:

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

In some cases, I have more than two <ContactPerson> so I would be nice to have a great loop to resolve this. I've tried to resolve the problem with a for loop but I always have the result:

John Wayne 78787878 [email protected] John Wayne 78787878 [email protected]
1
  • 2
    The XML is faulty. It has no root node and <PhoneMobileList> has no end tag. This can not be parsed with an XML parser.
    – Kusalananda
    CommentedFeb 9, 2018 at 11:30

3 Answers 3

3

Assuming the following (modified) 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> 

The XMLStarlet invocation

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

produces

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

The invocation of XMLStarlet contains an implicit loop over all ContactPerson nodes, and for each of these, the specific fields are concatenated to produce the correct output. The -nl at the end causes a newline to be printed.

5
  • Thank you Kusalananda. Is there any form to get the result without the xmlstarlet?
    – lendoiro
    CommentedFeb 9, 2018 at 11:51
  • 1
    @lendoiro XMLStarlet in the command line XML parser that I know best. You could possibly do it by means of sed and/or awk as well, but these are generally not good tools for parsing XML, and I will not write an answer using them.
    – Kusalananda
    CommentedFeb 9, 2018 at 12:05
  • Ok. I was triying with sed and/or awk but I couldn't resolve it. Thank you for your reply
    – lendoiro
    CommentedFeb 9, 2018 at 12:08
  • 1
    Don't even try to process XML with tools that don't understand XML.CommentedFeb 9, 2018 at 13:04
  • That last comment was probably for you @lendorio. I'm well aware of the issues with parsing XML using anything other than an XML parser.
    – Kusalananda
    CommentedFeb 9, 2018 at 13:32
1

With xml2 (and a shell with support for the $'...' quotes):

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

(for ContactPersons with more than one email address, the last one is returned)

    1

    If you're OK with having a second file for processing this, you can make an XSLT file and use it to transform your XML file using xsltproc.

    phones.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> 

    Then transform the file (using @Kusalananda's XML as phones.xml):

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

    Using XSLT has the advantage that you can loop through repeating elements, do conditional output and so forth. If you're comfortable with a bit of study and programming, it's very powerful.

      You must log in to answer this question.

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.