Need to read a csv and create xml - Perl

I have a csv file like below.

john,r2,testdomain1,john.r2@hex.com,DOMAINADMIN,testdomain1.dom
maxwell,b2, testdomain1,maxwell.b2@hex.com,DOMAINADMIN,testdomain1.dom

I would need the perl script to read the above csv and create an xml like below.

<Users>
        <DomainName>testdomain1</DomainName>
        <User>
            <UserName>john.r2.testdomain1.digitalsafe.net</UserName>
                <Password>
                <Value>Skyline@123</Value>
                </Password>
            <BillingGroupName>testdomain1</BillingGroupName>
            <DataSource>sa</DataSource>
            <UserProfile>
                <LastName>r2</LastName>
                <FirstName>john</FirstName>
                <ContactEmail>john.r2@hex.com</ContactEmail>
                <SendItToMe>nobody@zantaz.com</SendItToMe>
            </UserProfile>
        </User>
        <User>
            <UserName>maxwell.b2.testdomain1.digitalsafe.net</UserName>
                <Password>
                <Value>Skyline@123</Value>
                </Password>
            <BillingGroupName>testdomain1</BillingGroupName>
            <DataSource>sa</DataSource>
            <UserProfile>
                <LastName>b2</LastName>
                <FirstName>maxwell</FirstName>
                <ContactEmail>maxwell.b2@hex.com</ContactEmail>
                <SendItToMe>nobody@zantaz.com</SendItToMe>
            </UserProfile>
        </User>

</users>

<UserRoleAssignments>
<UserRoleAssignment>
            <UserName>john.r2.testdomain1.digitalsafe.net</UserName>
            <RoleName>EntityAccess</RoleName>
            <Entities>
                <Entity ns1:type="Applications">
                    <EntityName>ac</EntityName>
                </Entity>
            </Entities>
        </UserRoleAssignment>
        <UserRoleAssignment>
            <UserName>john.r2.testdomain1.digitalsafe.net</UserName>
            <RoleName>DomainAdmin</RoleName>
            <Entities>
                <Entity ns1:type="Applications">
                    <EntityName>adm</EntityName>
                </Entity>
            </Entities>
        </UserRoleAssignment>
<UserRoleAssignment>
            <UserName>john.r2.testdomain1.digitalsafe.net</UserName>
            <RoleName>DomainAdmin</RoleName>
            <Entities>
                <Entity ns1:type="Applications">
                    <EntityName>adm</EntityName>
                </Entity>
            </Entities>
        </UserRoleAssignment>
    </UserRoleAssignments>
</ZantazAccountManagement>

I wrote a script but its not capable of printing common xml tags in the output file.

use strict;

  # Open the ch2_xml_users.csv file for input
  open(CSV_FILE, "ch2_xmlusers.csv") ||
   die "Can't open file: $!";

  # Open the ch2_xmlusers.xml file for output
  open(XML_FILE, ">ch2_xmlusers.xml") ||
   die "Can't open file: $!";

 # Print the initial XML header and the root element
 print XML_FILE "<ZantazAccountManagement xmlns\=\"http\:\/\/www\.zantaz\.com\/\" xmlns\:xsi\=\"http\:\/\/www\.w3\.org\/2001\/XMLSchema\-instance\" xmlns\:ns1\=\"http\:\/\/www\.zantaz\.com\/\" xsi\:schemaLocation\=\"http\:\/\/www\.zantaz\.com\/ schema\.xsd\" ns1\:action\=\"UPDATE\">
";
print XML_FILE " <BillingGroups>
        <BillingGroup>
            <Name>testdomain1</Name>
            <Type>-</Type>
            <CustomerName>testdomain1</CustomerName>
        </BillingGroup>
    </BillingGroups>";

 # The while loop to traverse through each line in users.csv
 while(<CSV_FILE>) {
   chomp; # Delete the new line char for each line

   # Split each field, on the comma delimiter, into an array
   my @fields = split(/,/, $_);

 print XML_FILE<<"EOF";
 <DomainName>testdomain1</DomainName>
        <User>
            <UserName>$fields[0].$fields[1].$fields[3].$fields[4]</UserName>
                <Password>
                <Value>Skyline\@123</Value>
                </Password>
            <BillingGroupName>$fields[4]</BillingGroupName>
            <DataSource>sa</DataSource>
            <UserProfile>
                <LastName>$fields[1]</LastName>
                <FirstName>$fields[0]</FirstName>
                <ContactEmail>$fields[2]</ContactEmail>
                <SendItToMe>nobody\@zantaz.com</SendItToMe>
            </UserProfile>
        </User>
    <UserRoleAssignment>
            <UserName>$fields[0].$fields[1].$fields[3].$fields[4]</UserName>
            <RoleName>DomainAdmin</RoleName>
            <Entities>
                <Entity ns1:type="Applications">
                    <EntityName>adm</EntityName>
                </Entity>
            </Entities>
        </UserRoleAssignment>
        <UserRoleAssignment>
            <UserName>$fields[0].$fields[1].$fields[3].$fields[4]</UserName>
            <RoleName>Researcher</RoleName>
            <Entities>
                <Entity ns1:type="Applications">
                    <EntityName>ds</EntityName>
                </Entity>
            </Entities>
        </UserRoleAssignment>


EOF
 }

 # Close the root element

print XML_FILE "</ZantazAccountManagement>";

 # Close all open files
close CSV_FILE;
 close XML_FILE;

items marked in red are common tags in this xml. I am not sure how I can print them while working on while loop. Can any one help me with this please?

One way to do it would be to keep appending and "building" two different strings - one for all users and the other for all user role assignments inside the while loop.
Once you're done with the loop, append them and print to XML file.

Something like the following (updated code is in red):

$ 
$ cat csv2xml_v1.pl
#!perl
use strict;
# Open the ch2_xml_users.csv file for input
open(CSV_FILE, "ch2_xmlusers.csv") || die "Can't open file: $!";
# Open the ch2_xmlusers.xml file for output
open(XML_FILE, ">ch2_xmlusers.xml") || die "Can't open file: $!";
# Print the initial XML header and the root element
print XML_FILE "<ZantazAccountManagement xmlns\=\"http\:\/\/www\.zantaz\.com\/\" xmlns\:xsi\=\"http\:\/\/www\.w3\.org\/2001\/XMLSchema\-instance\" xmlns\:ns1\=\"http\:\/\/www\.zantaz\.com\/\" xsi\:schemaLocation\=\"http\:\/\/www\.zantaz\.com\/ schema\.xsd\" ns1\:action\=\"UPDATE\">";
print XML_FILE " <BillingGroups>
        <BillingGroup>
            <Name>testdomain1</Name>
            <Type>-</Type>
            <CustomerName>testdomain1</CustomerName>
        </BillingGroup>
    </BillingGroups>";
my $all_users = "";
my $all_user_role_assignments = "";
# The while loop to traverse through each line in users.csv
while(<CSV_FILE>) {
    chomp; # Delete the new line char for each line
    # Split each field, on the comma delimiter, into an array
    my @fields = split(/,/, $_);
    $all_users .= <<"EOF";
       <User>
           <UserName>$fields[0].$fields[1].$fields[3].$fields[4]</UserName>
               <Password>
               <Value>Skyline\@123</Value>
               </Password>
           <BillingGroupName>$fields[4]</BillingGroupName>
           <DataSource>sa</DataSource>
           <UserProfile>
               <LastName>$fields[1]</LastName>
               <FirstName>$fields[0]</FirstName>
               <ContactEmail>$fields[2]</ContactEmail>
               <SendItToMe>nobody\@zantaz.com</SendItToMe>
           </UserProfile>
       </User>
EOF
    $all_user_role_assignments .= <<"EOF";
    <UserRoleAssignment>
           <UserName>$fields[0].$fields[1].$fields[3].$fields[4]</UserName>
           <RoleName>DomainAdmin</RoleName>
           <Entities>
               <Entity ns1:type="Applications">
                   <EntityName>adm</EntityName>
               </Entity>
           </Entities>
       </UserRoleAssignment>
       <UserRoleAssignment>
           <UserName>$fields[0].$fields[1].$fields[3].$fields[4]</UserName>
           <RoleName>Researcher</RoleName>
           <Entities>
               <Entity ns1:type="Applications">
                   <EntityName>ds</EntityName>
               </Entity>
           </Entities>
       </UserRoleAssignment>
EOF
}
print XML_FILE "\n<DomainName>testdomain1</DomainName>\n<Users>\n".$all_users."\n</Users>\n";
print XML_FILE "<UserRoleAssignments>\n".$all_user_role_assignments."\n</UserRoleAssignments>\n";
# Close the root element
print XML_FILE "</ZantazAccountManagement>";
# Close all open files
close CSV_FILE;
close XML_FILE;
 
$
$
1 Like