Menu
Home
Log in / Register
 
Home arrow Computer Science arrow Python Programming Fundamentals
< Prev   CONTENTS   Next >

4.9 Reading an XML File and Building Parallel Lists

Drawing a picture like the one in Fig. 4.4 is possible if the corresponding XML file is parsed and the graphics commands extracted from it. Imagine that not only do we want to read such a picture, we would like to be able to scale the picture to make it bigger or smaller. It is possible to do this if we store all the graphics commands in lists. We'll store each graphics command and its attributes in separate lists. One list will hold all the graphic command names. Another will hold the color attribute of each graphic command. Still another will hold the x attribute of each command, and so on.

This technique of using multiple lists to hold data that are related to each other is called parallel lists. The lists are in a sense parallel to each other because each list contains information that is related to the others at the same index value within the list. Each index location within the six lists contains the six attributes of one graphics command. Since we will need to go through the data more than once if we are scaling the picture, it makes sense to store this information in parallel lists so we can go through it as often as we need.

If a particular graphic command, like BeginFill does not have an attribute, like x for instance, then a special value of None will be stored at that location in the list. In this way the parallel lists will all have the same length and all the related data for a graphics command will be stored at the same index location within all the lists. We'll name these parallel lists for their attribute names with a List attached to the end. So the list of x attributes becomes xList for example. The graphic command list will just be called commandList.

Example 4.9 Code to build these parallel lists is relatively simple. There are five attributes. Each of these attributes corresponds to one list. Line 14 of the code in this example deserves some further explanation. In this line the expression command.firstChild.data retrieves the text appearing between the start-tag and end-tag of an XML element. For instance, when examining the element from line three of the XML file in Example 4.7 the command.firstChild.data would be “BeginFill”. The text in between the tags tells the code in this example which graphics command is represented in each of the XML elements.

1 import turtle

2 from xml . dom import minidom

3 xmldoc = minidom . parse (" flowerandbg . xml ")

4 graphicsCommand =

5 xmldoc . getElementsByTagName (" GraphicsCommands " )[ 0 ]

6 commands = graphicsCommand . getElementsByTagName (" Command ")

7 commandList = []

8 xList = []

9 yList = []

10 widthList = []

11 colorList = []

12 radiusList = []

13 for command in commands :

14 commandList . append ( command . firstChild . data . strip ())

15 attr = command . attributes

16 i f "x" in attr :

17 xList . append ( attr ["x" ]. value )

18 e l s e :

19 xList . append ( None )

20 i f "y" in attr :

21 yList . append ( attr ["y" ]. value )

22 e l s e :

23 yList . append ( None )

24 i f " width " in attr :

25 widthList . append ( attr [" width " ]. value )

26 e l s e :

27 widthList . append ( None )

28 i f " color " in attr :

29 colorList . append ( attr [" color " ]. value )

30 e l s e :

31 colorList . append ( None )

32 i f " radius " in attr :

33 radiusList . append ( attr [" radius " ]. value )

34 e l s e :

35 radiusList . append ( None )

The code above is very repetitive on lines 17–36 doing the same thing for each attribute. All that changes is the attribute name and the list to which the value is appended. This code could be rewritten to use two parallel lists of its own, one for the attribute names, and another for the attribute lists. So, we end up with two more lists, the attrributeList and the attributes list. This shortens the code considerably. This code does exactly the same thing as the code above.

1 import turtle

2 from xml . dom import minidom

3 xmldoc = minidom . parse (" flowerandbg . xml ")

4 graphicsCommand =

5 xmldoc . getElementsByTagName (" GraphicsCommands " )[ 0 ]

6 commands = graphicsCommand . getElementsByTagName (" Command ")

7 commandList = []

8 xList = []

9 yList = []

10 widthList = []

11 colorList = []

12 radiusList = []

13 attributeList = [ xList , yList , widthList , colorList , radiusList ]

14 attributes = ["x" ,"y" ," width " ," color " ," radius "]

15 for command in commands :

16 commandList . append ( command . firstChild . data . strip ())

17 attr = command . attributes

18

19 for i in r a n g e ( len ( attributes )):

20 attr = command . attributes

21 key = attributes [ i]

22 i f key in attr :

23 attributeList [ i ]. append ( attr [ key ]. value )

24 e l s e :

25 attributeList [ i ]. append ( None )

Notice the way the code above iterates over the attributes. Since the attributes list and the attributeList list are the same length the for i in range(len(attributes)) generates the index i into both parallel lists. When working with parallel lists you always use an indexed for loop like this or while loop so you have an index that you can use to index into any of the parallel lists.

 
Found a mistake? Please highlight the word and press Shift + Enter  
< Prev   CONTENTS   Next >
 
Subjects
Accounting
Business & Finance
Communication
Computer Science
Economics
Education
Engineering
Environment
Geography
Health
History
Language & Literature
Law
Management
Marketing
Philosophy
Political science
Psychology
Religion
Sociology
Travel