How do I sort XML alphabetically using python?

324 Views Asked by At

I have some XML files that i want to sort by the element name. These xml files are considered used as Profiles in my salesforce sandbox/org. Ive built some code that takes an xml file and appends it to the bottom of each profile xml file.Allowing me to add code to multiple files all at once rather than having to copy/paste to each file. The issue here, the xml needs to be sorted alphabetically by the element name, ex:(classAccesses, fieldPermissions, layoutAssignments, recordTypeVisibilities, objectPermissions) I have pasted an example of the xml below. The format of the file needs to be consistent and cant change as salesforce might not like it.

<?xml version="1.0" encoding="UTF-8"?>
<Profile xmlns="http://soap.sforce.com/2006/04/metadata">
    <fieldPermissions>
        <editable>false</editable>
        <field>Branch_Queue__c.Cell_Phone_Number__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>false</editable>
        <field>Branch_Queue__c.Branch__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>false</editable>
        <field>Branch_Queue__c.Source__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <editable>false</editable>
        <field>Branch_Queue__c.Served_By__c</field>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
            <editable>false</editable>
            <field>Branch_Queue__c.Update__c</field>
            <readable>true</readable>
    </fieldPermissions>
    <recordTypeVisibilities>
        <default>false</default>
        <recordType>Knowledge__kav.RealEstate</recordType>
        <visible>true</visible>
    </recordTypeVisibilities>
    <recordTypeVisibilities>
        <default>false</default>
        <recordType>Knowledge__kav.RealEstate_Community_Connection</recordType>
        <visible>true</visible>
    </recordTypeVisibilities>
     <objectPermissions>
        <allowCreate>false</allowCreate>
        <allowDelete>false</allowDelete>
        <allowEdit>false</allowEdit>
        <allowRead>true</allowRead>
        <modifyAllRecords>false</modifyAllRecords>
        <object>Branch_Queue__c</object>
        <viewAllRecords>true</viewAllRecords>
    </objectPermissions>
    <classAccesses>
        <apexClass>BranchQueueDisplayList</apexClass>
        <enabled>true</enabled>
    </classAccesses>
    <classAccesses>
        <apexClass>BranchQueueDisplayList_Test</apexClass>
        <enabled>true</enabled>
    </classAccesses>
    <classAccesses>
        <apexClass>BranchQueueService</apexClass>
        <enabled>true</enabled>
    </classAccesses>
</Profile>

if it helps, here is the python script i have built. if you have any questions please feel free to ask. Thanks!

import os 
import json
directory = 'C:/Users/HB35401/MAXDev/force-app/main/default/profiles' #folder containing profiles to be modified
os.chdir(directory)
newData = 'C:/testXMLBatch/additionalXML/addXML.xml' #xml file to append to profile-xml files.

for nameOfFile in os.listdir(directory): #for each profile in the directory
    if nameOfFile.endswith(".xml"):
        g = open(newData)
        data = g.read() #set the value of the newXML to the data variable
        f = open(nameOfFile)
        fileContent = f.read() #save the content of the profile to fileContent
        if data in fileContent:
            print('ERROR: XML is already inside the Profile.' + nameOfFile)
        else:
            EndLine = fileContent[-11:] #save the </Profile> tag from the bottom of the file to EndLine variable.
            #print(EndLine)            # theEndLine will be appended back after we add our new XML.
            test = fileContent[:-11] #remove the </Profile> tag and write back to the profile the removal of the </Profile> tag
            with open(nameOfFile, "w") as w:
                w.write(test)
            with open(nameOfFile) as t:
                fileContent2 = t.read()
                #print(fileContent2)   

            h = open(nameOfFile, "a") #add the new data to the profile along with the </Profile> tag
            h.write(data + "\n"+ EndLine)
            h.close()
1

There are 1 best solutions below

0
dabingsou On

Try this .

from simplified_scrapy import SimplifiedDoc, utils
xml = utils.getFileContent('your xml file.xml')
doc = SimplifiedDoc(xml)
root = doc.Profile
nodes = root.children # Get all nodes

count = len(nodes)
if count:
    sorted_nodes = sorted(nodes, key=operator.itemgetter('tag')) # Sort by tag
    sorted_htmls = []
    for node in sorted_nodes:
        sorted_htmls.append(node.outerHtml) # Get the string of sorted nodes
    for i in range(0, count):
        nodes[i].repleaceSelf(sorted_htmls[i]) # Replace the nodes in the original text with the sorted nodes

print(doc.html)