Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Create XML from dictionary
#1
Hi all,

I have a dictionary that is grouped by terms. The terms then has a list of users associated with it. The following is the dictionary:

defaultdict(<class 'list'>, {'06242019': [5717424, 5708813, 5709635, 5711802, 5712915, 5724011, 5710878, 5731039, 5714326, 5724787, 5720029], '06102019': [5664036]})

I am using ElementTree to create an XMl file based on this grouping.

def prettify(elem):
    rough_string = ElementTree.tostring(elem, encoding='UTF-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="    ")

top = Element('enterprise')
comment = Comment('XML to generate Sandbox Enrollments')
top.append(comment)

propertiesParent = SubElement(top, 'properties', {'lang':"EN"})

propertiesChildren = SubElement(propertiesParent, 'datasource')
propertiesChildren.text = "Campus Nexus"
propertiesChildren = SubElement(propertiesParent, 'target')
propertiesChildren.text = "UMA Blackboard"
propertiesChildren = SubElement(propertiesParent, 'type')
propertiesChildren.text = "XML"

groupParent1 = SubElement(top, 'membership')
comment = Comment('Enroll users in the Orientation section')
groupParent1.append(comment)

groupChild1 = SubElement(groupParent1, 'sourcedid')
groupChild1a = SubElement(groupChild1, 'source')
groupChild1a.text = "Campus Nexus"
groupChild1b = SubElement(groupChild1, 'id')
groupChild1b.text = enrollDict[0]

groupChild2 = SubElement(groupParent1, 'member')
groupChild2a = SubElement(groupChild2, 'sourcedid')
groupChild2b = SubElement(groupChild2a, 'source')
groupChild2b.text = "Campus Nexus"
groupChild2b = SubElement(groupChild2a, 'id')
groupChild2b.text = "SyStudent_" + str(enrollDict[key])
This creates a subelement for every child element though instead of grouping them by the term. Can any please shed light on how I can get this to work? Thanks!
Reply
#2
In what way is your current output different from your desired output?
It isn't clear how the dict key/values are supposed to map to xml elements.
Reply
#3
Hi nilamo,

Thanks for your reply. I have resolved my issue. Before, the output was creating the enrollment file I needed as such:

<?xml version="1.0" ?>
<enterprise>
<!--XML to generate Sandbox Enrollments-->
<properties lang="EN">
<datasource>Campus Nexus</datasource>
<target>UMA Blackboard</target>
<type>XML</type>
</properties>
<membership>
<!--Enroll users in the Orientation section-->
<sourcedid>
<source>Campus Nexus</source>
<id>06242019_001</id>
</sourcedid>
<member>
<sourcedid>
<source>Campus Nexus</source>
<id>SyStudent_5717424</id>
</sourcedid>
</member>
</membership>
<membership>
<!--Enroll users in the Orientation section-->
<sourcedid>
<source>Campus Nexus</source>
<id>06242019_001</id>
</sourcedid>
<member>
<sourcedid>
<source>Campus Nexus</source>
<id>SyStudent_5708813</id>
</sourcedid>
</member>
</membership>
<membership>
<!--Enroll users in the Orientation section-->
<sourcedid>
<source>Campus Nexus</source>
<id>06242019_001</id>
</sourcedid>
<member>
<sourcedid>
<source>Campus Nexus</source>
<id>SyStudent_5709635</id>
</sourcedid>
</member>
</membership>
</enterprise>

Notice that a membership tag is created for each term for each student. The format I need is this:

<?xml version="1.0" ?>
<enterprise>
<!--XML to generate Sandbox Enrollments-->
<properties lang="EN">
<datasource>Campus Nexus</datasource>
<target>UMA Blackboard</target>
<type>XML</type>
</properties>
<membership>
<!--Enroll users in the Orientation section-->
<sourcedid>
<source>Campus Nexus</source>
<id>06102019_001</id>
</sourcedid>
<member>
<sourcedid>
<source>Campus Nexus</source>
<id>SyStudent_5664036</id>
</sourcedid>
<idtype>1</idtype>
<role roletype="1">
<status>1</status>
<extension>
<x_bb_available>Y</x_bb_available>
<x_bb_row_status>0</x_bb_row_status>
<x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key>
</extension>
</role>
</member>
</membership>
<membership>
<!--Enroll users in the Orientation section-->
<sourcedid>
<source>Campus Nexus</source>
<id>06242019_001</id>
</sourcedid>
<member>
<sourcedid>
<source>Campus Nexus</source>
<id>SyStudent_5717424</id>
</sourcedid>
<idtype>1</idtype>
<role roletype="1">
<status>1</status>
<extension>
<x_bb_available>Y</x_bb_available>
<x_bb_row_status>0</x_bb_row_status>
<x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key>
</extension>
</role>
</member>
<member>
<sourcedid>
<source>Campus Nexus</source>
<id>SyStudent_5708813</id>
</sourcedid>
<idtype>1</idtype>
<role roletype="1">
<status>1</status>
<extension>
<x_bb_available>Y</x_bb_available>
<x_bb_row_status>0</x_bb_row_status>
<x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key>
</extension>
</role>
</member>
</membership>
</enterprise>

So multiple students enrolled under one single term. I was able to accomplish this byt the following code:

from collections import defaultdict
from xml.dom import minidom
from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement, Comment

#RETURN A PRETTY-PRINTED XML STRING FOR THE FEEDFILE.
def prettify(elem):
    rough_string = ElementTree.tostring(elem, encoding='UTF-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="    ")

enrollmentDict = defaultdict(list)
for xsDate, syId in newEnrollments:
    enrollmentDict[xsDate].append(syId)
#print("dict", enrollmentDict, '\n')

#CREATE XML FEED FILE HEADER
top = Element('enterprise')
comment = Comment('XML to generate Sandbox Enrollments')
top.append(comment)

propertiesParent = SubElement(top, 'properties', {'lang':"EN"})

propertiesChildren = SubElement(propertiesParent, 'datasource')
propertiesChildren.text = "Campus Nexus"
propertiesChildren = SubElement(propertiesParent, 'target')
propertiesChildren.text = "UMA Blackboard"
propertiesChildren = SubElement(propertiesParent, 'type')
propertiesChildren.text = "XML"

for key in enrollmentDict:
    groupParent1 = SubElement(top, 'membership')
    comment = Comment('Enroll users in the Orientation section')
    groupParent1.append(comment)

    groupChild1 = SubElement(groupParent1, 'sourcedid')
    groupChild1a = SubElement(groupChild1, 'source')
    groupChild1a.text = "Campus Nexus"
    groupChild1b = SubElement(groupChild1, 'id')
    groupChild1b.text = key + "_001"

    for value in range(len(enrollmentDict[key])):
        groupChild2 = SubElement(groupParent1, 'member')
        groupChild2a = SubElement(groupChild2, 'sourcedid')
        groupChild2b = SubElement(groupChild2a, 'source')
        groupChild2b.text = "Campus Nexus"
        groupChild2b = SubElement(groupChild2a, 'id')
        groupChild2b.text = "SyStudent_" + str(enrollmentDict[key][value])

        groupChild3 = SubElement(groupChild2, 'idtype')
        groupChild3.text = '1'

        groupChild4 = SubElement(groupChild2, 'role', roletype = '1')

        groupChild5 = SubElement(groupChild4, 'status')
        groupChild5.text = '1'

        groupChild6 = SubElement(groupChild4, 'extension')
        groupChild6a = SubElement(groupChild6, 'x_bb_available')
        groupChild6a.text = 'Y'
        groupChild6b = SubElement(groupChild6, 'x_bb_row_status')
        groupChild6b.text = '0'
        groupChild6c = SubElement(groupChild6, 'x_bb_datasource_key')
        groupChild6c.text = 'MEMBERS.TXT'

print(prettify(top))
I hope this can help others struggling with this same issue.
Reply
#4
In an effort to make my code more "pythonic" and to include new requirements, I modified it to use functions for the various parts of the program. This put me back at square one with my problem. So here is the new issue:

I need to create and XML file for enrollments into various sections. The max number of sections per term is 40. The max number of students per section is 20. I also take into account the number of users already enrolled into a particular section, so if there are already 10 enrolled my XML should only generate for 10 more students. If there are more than 10 remaining students to enroll, a new section needs to be created and the process repeats. The original dictionary of new students contains the following data:

new students defaultdict(<class 'list'>, {'07292019': [5764146, 5764208, 5628056, 5764962, 5765238, 5765098, 5505275, 5764173, 5758004, 5710184, 4281360, 5724284, 5733611, 5664975, 5763188, 5763632, 5761705, 5764626, 5755932, 2749228, 5763146, 5763767, 141868, 5764928, 5764098, 5765211, 5197807, 5758318, 5591460, 5765007, 4331521, 2316969, 5762638, 5020512, 5742032, 5735627, 5012332, 5757641, 5765152, 5619975, 5762265, 5751185, 5764934, 5760885, 5764641, 5759250, 5756844, 5640685, 5741031, 4548617, 5516464, 5760699, 1755282, 3124116, 5756089, 5764854, 5762379, 5764795, 5734983, 5743824, 5647198, 4189658, 2864329, 5764805, 5764484, 5736883, 3222262, 3913367, 5765180, 5760120, 5763736, 5764400, 5764920, 5174953, 5755354, 1818845, 5765071, 5765024, 5737104, 3911357, 5764094, 5760259, 5744785, 5764790, 5196707, 5763599, 5763919, 5309074, 5758499, 4153299, 5763834, 5758908, 5764293, 5748717, 5747788, 5760961, 5764277, 5764750, 5747557, 3255138, 5764997, 5518793, 5762890, 5763094, 5765173, 5764496, 5733927, 2856506, 5763932, 5762777, 5038537, 626824, 5761819, 3150933, 5764796, 5763820, 5764038, 5763600, 5611245, 2350080, 5760793, 5494648, 5761753, 1554277, 5607548, 5765026, 3636089, 260446, 5764183, 5761714, 5581201, 5763694, 4648783, 5763733, 5764083, 5765029, 5764337, 5754852, 5765107, 5759288, 5765137, 5736457, 5023053, 5755798, 2934085, 5745608, 5755050, 5764494, 5764902, 5763917, 5764407, 5748954, 5760964, 5753269, 5751431, 4610224, 5765111, 5764835, 1068460, 5750322, 1626712, 5764296, 4875391, 5484910, 807811, 5764687, 5765011, 5763639, 3206502, 5764214, 5764592, 371518, 5763223, 5765144, 5765280, 5764925, 5762446, 5764301, 5761136, 5763961, 4252721, 5628297, 5110022, 5765175, 5764591, 4766019, 5734281, 5760056, 3212906, 5765089, 5759291, 5764989, 5761555, 5739075, 5758566, 5763804, 5763687, 5760210, 5763893, 4058257, 5764018, 2602095, 3091127, 5765093, 5762571, 5762951, 509021, 5665917, 3440598, 4767701, 5764003, 5639083, 5761191, 5758913, 5763925, 5751723, 1971322, 5652868, 5765114, 4890931, 5298765, 3627468, 5764335, 5742484, 4107920, 5755649, 5764524, 4774336, 5764500, 3393552, 5753368, 5764116, 5746728, 5764136, 1287969, 5764156, 5765212, 5760509, 5744859, 1018083, 4509889, 5764218, 5763659, 5368815, 1098686, 4559495, 3829964, 4584229, 4432291, 4333698, 3695445, 5759103, 5759038, 5759180, 5758893, 3871343, 4368225, 3922298, 4049434, 4521245, 4426735, 4455728, 4291088, 4693206, 4584675], '08192019': [5759515, 5759552, 5759554, 5759039, 5759043, 5759044, 5759577, 5759036, 5759242]})

The counts of already existing students in existing terms/sections are:

count {'07152019_001': 200, '07152019_002': 201, '07292019_001': 9, '07152019_003': 171, '04152019_001': 1}

Since there are already 9 students enrolled into section 1 for term 07292019_001, I need to enroll the first 11 new students into the section, then enroll the next 20 into section 2 and so on.

My code is as follows:

import pyodbc
from datetime import datetime as dt
from collections import defaultdict
from xml.dom import minidom
from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement, Comment

#GET LIST OF NEW ENROLLMENTS TO PROCESS
def get_new_enrollments(cursor):
    SQL1 = "SELECT  ExpectedStartDate, SyStudentID FROM [LMS_Data].[OrientationStudentInformation] WHERE OrientationSection IS NULL order by ExpectedStartDate asc"
    cursor.execute(SQL1)
    newEnrolls = cursor.fetchall()
    newEnrollments = []
    if not newEnrolls:
        print("There are no new enrollments to process for Sandbox.")
    else:
        for row in newEnrolls:
            expStartDate = dt.strftime(row[0], '%m%d%Y')
            row[0] = expStartDate
            newEnrollments.append(row)

        enrollmentDict = defaultdict(list)
        for xsDate, syId in newEnrollments:
            enrollmentDict[xsDate].append(syId)
    return(enrollmentDict)

#RETURN A PRETTY-PRINTED XML STRING FOR THE FEEDFILE
def prettify(elem):
    rough_string = ElementTree.tostring(elem, encoding='UTF-8')
    reparsed = minidom.parseString(rough_string)
    return(reparsed.toprettyxml(indent="    "))

#GET CURRENT COUNT OF ENROLLMENTS BY SECTION FROM DB TABLE
def current_enrollment_count(cursor):
    SQL2 = ("SELECT OrientationSection, SyStudentID from [LMS_Data].[OrientationStudentInformation] where OrientationSection IS NOT NULL")
    cursor.execute(SQL2)
    currEnroll = cursor.fetchall()

    sectionDict = {}
    for section, student in currEnroll:
        sectionDict.setdefault(section, []).append(student)

    numStudents = {}
    for sec, stu in sectionDict.items():
        numStudents.update({sec: len(stu)})
    return(numStudents)

#CREATE XML FEED FILE
def create_xml(newStudents, sectionCount, cursor):
    numSection = 1
    maxEnroll = 20
    print("new students", newStudents)
    print("count", sectionCount)

    #XML HEADER
    top = Element('enterprise')
    comment = Comment('XML to Process Sandbox Enrollments')
    top.append(comment)

    propertiesParent = SubElement(top, 'properties', {'lang':"EN"})

    propertiesChildren = SubElement(propertiesParent, 'datasource')
    propertiesChildren.text = "Campus Nexus"
    propertiesChildren = SubElement(propertiesParent, 'target')
    propertiesChildren.text = "UMA Blackboard"
    propertiesChildren = SubElement(propertiesParent, 'type')
    propertiesChildren.text = "XML"

    #GET COUNT FOR SECTIONS FOUND FOR NEW STUDENTS (IF EXISTS)
    for xsDate,sList in newStudents.items():
        tmpSects = {k:v for k,v in sectionCount.items() if xsDate in k}
        print("tempsects",tmpSects)

        for stu in sList:
            if all([v >= maxEnroll for v in tmpSects.values()]):
                secNums = [int(k.split('_')[1]) for k in tmpSects.keys()]
                numSection = max(secNums, default=0) + 1
                print("numSection", numSection)

            if numSection <= 9:
                section = f'{xsDate}_00{numSection}'
            else:
                section = f'{xsDate}_0{numSection}'
                tmpSects[section] = 1
            print('section',section)

            groupParent1 = SubElement(top, 'membership')
            comment = Comment('Enroll users in the Sandbox section')
            groupParent1.append(comment)

            groupChild1 = SubElement(groupParent1, 'sourcedid')
            groupChild1a = SubElement(groupChild1, 'source')
            groupChild1a.text = "Campus Nexus"
            groupChild1b = SubElement(groupChild1, 'id')
            groupChild1b.text = section

            groupChild2 = SubElement(groupParent1, 'member')
            groupChild2a = SubElement(groupChild2, 'sourcedid')
            groupChild2b = SubElement(groupChild2a, 'source')
            groupChild2b.text = "Campus Nexus"
            groupChild2b = SubElement(groupChild2a, 'id')
            groupChild2b.text = "SyStudent_" + str(stu)

            groupChild3 = SubElement(groupChild2, 'idtype')
            groupChild3.text = '1'

            groupChild4 = SubElement(groupChild2, 'role', roletype = '1')

            groupChild5 = SubElement(groupChild4, 'status')
            groupChild5.text = '1'

            groupChild6 = SubElement(groupChild4, 'extension')
            groupChild6a = SubElement(groupChild6, 'x_bb_available')
            groupChild6a.text = 'Y'
            groupChild6b = SubElement(groupChild6, 'x_bb_row_status')
            groupChild6b.text = '0'
            groupChild6c = SubElement(groupChild6, 'x_bb_datasource_key')
            groupChild6c.text = 'MEMBERS.TXT'
    else:
        for k,v in tmpSects.items():
            if v < maxEnroll:
                numSection = int(k.split('_')[1])
            if numSection <= 9:
                section = f'{xsDate}_00{numSection}'
            else:
                section = f'{xsDate}_0{numSection}'
            tmpSects[section] += 1

    print(prettify(top))

#CONNECT TO SQL DATABASE
cnxn = pyodbc.connect("Driver={SQL Server Native Client 11.0};"
                      "Server=MLK-CVU-U-SQ02;"
                      "Database=FREEDOM;"
                      "Trusted_Connection=yes;")
cursor = cnxn.cursor()

newStudents = get_new_enrollments(cursor)
sectionCount = current_enrollment_count(cursor)
create_xml(newStudents, sectionCount, cursor)

cursor.close()
cnxn.close()
print("SQL connection closed.")
This code currently generates the XML file as this:

Output:
<?xml version="1.0" ?> <enterprise> <!--XML to Process Sandbox Enrollments--> <properties lang="EN"> <datasource>Campus Nexus</datasource> <target>UMA Blackboard</target> <type>XML</type> </properties> <membership> <!--Enroll users in the Sandbox section--> <sourcedid> <source>Campus Nexus</source> <id>07292019_001</id> </sourcedid> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5764146</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> </membership> <membership> <!--Enroll users in the Sandbox section--> <sourcedid> <source>Campus Nexus</source> <id>07292019_001</id> </sourcedid> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5764208</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> </membership> </enterprise>
But it needs to format as this:

Output:
<?xml version="1.0" ?> <enterprise> <!--XML to Process Sandbox Enrollments--> <properties lang="EN"> <datasource>Campus Nexus</datasource> <target>UMA Blackboard</target> <type>XML</type> </properties> <membership> <!--Enroll users in the Sandbox section--> <sourcedid> <source>Campus Nexus</source> <id>07292019_001</id> </sourcedid> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5764146</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5764208</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> </membership> </enterprise>
Any insight would be greatly appreciated!!
Reply
#5
I think you want this: groupParent1 = SubElement(top, 'membership') to be outside the for-loop, so there's only one of them.
Reply
#6
(Jul-29-2019, 04:20 PM)nilamo Wrote: I think you want this: groupParent1 = SubElement(top, 'membership') to be outside the for-loop, so there's only one of them.

Hi nilamo,

Thanks for the reply! Please note that I have only been programming in python for a year so am very new to all of the options available. So, I am grateful for any help and insight!

This is what I have so far after making changes based on changes in requirements:

import os
import sys
import pyodbc
import requests
from datetime import datetime as dt
from collections import defaultdict
from xml.dom import minidom
from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement, Comment

#GET LIST OF NEW ENROLLMENTS TO PROCESS
def get_new_enrollments(cursor):
    SQL1 = "SELECT  ExpectedStartDate, SyStudentID FROM [LMS_Data].[OrientationStudentInformation] WHERE OrientationSection IS NULL order by ExpectedStartDate asc"
    cursor.execute(SQL1)
    newEnrolls = cursor.fetchall()
    newEnrollments = []
    if not newEnrolls:
        print("There are no new enrollments to process for Sandbox.")
        sys.exit()
    else:
        for row in newEnrolls:
            expStartDate = dt.strftime(row[0], '%m%d%Y')
            row[0] = expStartDate
            newEnrollments.append(row)

        enrollmentDict = defaultdict(list)
        for xsDate, syId in newEnrollments:
            enrollmentDict[xsDate].append(syId)

        return(enrollmentDict)

#RETURN A PRETTY-PRINTED XML STRING FOR THE FEEDFILE
def prettify(elem):
    rough_string = ElementTree.tostring(elem, encoding='UTF-8')
    reparsed = minidom.parseString(rough_string)
    return(reparsed.toprettyxml(indent="    "))

#GET CURRENT COUNT OF ENROLLMENTS BY SECTION FROM DB TABLE
def current_enrollment_count(cursor):
    SQL2 = ("SELECT OrientationSection, SyStudentID from [LMS_Data].[OrientationStudentInformation] where OrientationSection IS NOT NULL")
    cursor.execute(SQL2)
    currEnroll = cursor.fetchall()

    sectionDict = {}
    for section, student in currEnroll:
        sectionDict.setdefault(section, []).append(student)

    sectionCount = {}
    for sec, stu in sectionDict.items():
        sectionCount.update({sec: len(stu)})
    return(sectionCount)

#CREATE XML FEED FILE
def create_xml(newStudents, numStudents, cursor):
    #XML HEADER
    top = Element('enterprise')
    comment = Comment('XML to Process Sandbox Enrollments')
    top.append(comment)

    propertiesParent = SubElement(top, 'properties', {'lang':"EN"})

    propertiesChildren = SubElement(propertiesParent, 'datasource')
    propertiesChildren.text = "Campus Nexus"
    propertiesChildren = SubElement(propertiesParent, 'target')
    propertiesChildren.text = "UMA Blackboard"
    propertiesChildren = SubElement(propertiesParent, 'type')
    propertiesChildren.text = "XML"

    #COUNT OF EXISTING STUDENTS IN EXISTING SECTIONS FOR NEW STUDENTS' START DATES
    for xsDate,sList in newStudents.items():
        tmpSects = {k:v for k,v in numStudents.items() if xsDate in k}
        print("tempsects",tmpSects)

    maxEnroll = 3
    ctr = 0
    insertData = []
    for key in newStudents:
        numSection = 1
        if numSection <= 9:
            section = f'CourseSandbox_{key}_00{numSection}'
        else:
            section = f'CourseSandbox_{key}_0{numSection}'

        groupParent1 = SubElement(top, 'membership')
        comment = Comment('Enroll users in the Sandbox section')
        groupParent1.append(comment)

        groupChild1 = SubElement(groupParent1, 'sourcedid')
        groupChild1a = SubElement(groupChild1, 'source')
        groupChild1a.text = "Campus Nexus"
        groupChild1b = SubElement(groupChild1, 'id')
        groupChild1b.text = section

        #GENERATE XML BODY FOR ENROLLMENTS AND PARENT GROUPING FOR NEW SECTIONS CREATED
        for value in range(len(newStudents[key])):
            if ctr > maxEnroll - 1:
                ctr = 0
                numSection += 1

                if numSection <= 9:
                    section = f'CourseSandbox_{key}_00{numSection}'
                else:
                    section = f'CourseSandbox_{key}_0{numSection}'

                groupParent1 = SubElement(top, 'membership')
                comment = Comment('Enroll users in the Sandbox section')
                groupParent1.append(comment)

                groupChild1 = SubElement(groupParent1, 'sourcedid')
                groupChild1a = SubElement(groupChild1, 'source')
                groupChild1a.text = "Campus Nexus"
                groupChild1b = SubElement(groupChild1, 'id')
                groupChild1b.text = section

            ctr += 1
            groupChild2 = SubElement(groupParent1, 'member')
            groupChild2a = SubElement(groupChild2, 'sourcedid')
            groupChild2b = SubElement(groupChild2a, 'source')
            groupChild2b.text = "Campus Nexus"
            groupChild2b = SubElement(groupChild2a, 'id')
            groupChild2b.text = "SyStudent_" + str(newStudents[key][value])

            groupChild3 = SubElement(groupChild2, 'idtype')
            groupChild3.text = '1'

            groupChild4 = SubElement(groupChild2, 'role', roletype = '1')

            groupChild5 = SubElement(groupChild4, 'status')
            groupChild5.text = '1'

            groupChild6 = SubElement(groupChild4, 'extension')
            groupChild6a = SubElement(groupChild6, 'x_bb_available')
            groupChild6a.text = 'Y'
            groupChild6b = SubElement(groupChild6, 'x_bb_row_status')
            groupChild6b.text = '0'
            groupChild6c = SubElement(groupChild6, 'x_bb_datasource_key')
            groupChild6c.text = 'MEMBERS.TXT'
            insertData.append([groupChild1b.text, str(newStudents[key][value])])
    numSection += 1

    print(prettify(top))
So now I have to take into account any students already enrolled into existing sections. Then only add new ones. So, if the total number of enrollments per section is 20 and there are 20 enrollments in section 001 and 15 enrolled in section 002 and there are 10 new enrollments to process, I need to enroll the first 5 new users in section 002 and the remaining 5 in section 003.

I received the following piece of code from a "colleague" but have no idea how to incorporate it into my existing code or if it can even be used for my purposes. When I try to, it messes up the entire formatting of the XML file...again. Here is the codepiece:

if all([v >= maxEnroll for v in tmpSects.values()]):
    secNums = [int(k.split('_')[1]) for k in tmpSects.keys()]
    numSection = max(secNums, default=0) + 1
Again, any help is appreciated!! Wall
Reply
#7
Looks like you're still generating multiple memberships. I thought you only wanted one?
Reply
#8
(Jul-29-2019, 08:29 PM)nilamo Wrote: Looks like you're still generating multiple memberships. I thought you only wanted one?

Hi nilamo,

The output needed is:

Output:
<?xml version="1.0" ?> <enterprise> <!--XML to Process Sandbox Enrollments--> <properties lang="EN"> <datasource>Campus Nexus</datasource> <target>UMA Blackboard</target> <type>XML</type> </properties> <membership> <!--Enroll users in the Sandbox section--> <sourcedid> <source>Campus Nexus</source> <id>CourseSandbox_08192019_001</id> </sourcedid> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5759242</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5759515</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5759552</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> </membership> <membership> <!--Enroll users in the Sandbox section--> <sourcedid> <source>Campus Nexus</source> <id>CourseSandbox_08192019_002</id> </sourcedid> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5759554</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5759039</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5759043</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> </membership> <membership> <!--Enroll users in the Sandbox section--> <sourcedid> <source>Campus Nexus</source> <id>CourseSandbox_08192019_003</id> </sourcedid> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5759044</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5759577</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> <member> <sourcedid> <source>Campus Nexus</source> <id>SyStudent_5759036</id> </sourcedid> <idtype>1</idtype> <role roletype="1"> <status>1</status> <extension> <x_bb_available>Y</x_bb_available> <x_bb_row_status>0</x_bb_row_status> <x_bb_datasource_key>MEMBERS.TXT</x_bb_datasource_key> </extension> </role> </member> </membership> </enterprise>
But if there is an existing enrollment for the first section - CourseSandbox_08192019_001 - then it would only process two enrollments for this section since the max enrollment for a section in this code is 3.

Sorry if I am not explaining properly.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Create new dictionary angus1964 6 2,014 May-08-2022, 12:43 PM
Last Post: snippsat
  Create new dictionary angus1964 2 1,223 May-06-2022, 02:14 PM
Last Post: deanhystad
  Create a dynamic Menu from a editable Dictionary. KiNeMs 1 2,252 Jan-28-2020, 04:27 AM
Last Post: Larz60+
  Need to create a dictionary from a *.csv 74razor 5 2,946 Dec-18-2019, 08:57 PM
Last Post: ichabod801
  Create a dictionary from a list klllmmm 3 2,921 Oct-06-2019, 05:50 PM
Last Post: Gribouillis
  Better way to create nested dictionary with defaultdict() x2mlh 8 21,533 Nov-30-2017, 08:10 PM
Last Post: buran
  create dictionary from **kwargs that include tuple bluefrog 2 4,822 Oct-26-2016, 10:24 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020