2
votes

I'm new to python and am having trouble with a small script.

The for loop as defined currently only runs once.

Here's the code (there's 8 elements in each line):

#!/usr/local/bin/python

def string_to_xml(string):
    entries = string.split(',')
    result = "<item>\n"
    result += "\t<distributor>" + entries[0] + "</distributor>\n"
    result += "\t<number>" + entries[1] + "</number>\n"
    result += "\t<description>" + entries[2] + "</description>\n"
    result += "\t<brand>" + entries[3] + "</brand>\n"
    result += "\t<casesize>" + entries[4] + "</casesize>\n"
    result += "\t<unitsize>" + entries[5] + "</unitsize>\n"
    result += "\t<caseprice>" + entries[6] + "</caseprice>\n"
    result += "\t<unitprice>" + entries[7] + "</unitprice>\n"
    result += "</item>"
    return result

with open("input.csv") as csvfile:
    for line in csvfile:
        print string_to_xml(line)

Like this, it only prints the result of calling string_to_xml once. If I change the statement in the for loop to this:

for line in csvfile:
    print line

It correctly prints every line of the file.

Why does calling my function string_to_xml cause the loop to only run once?

edit: Here's the first two lines of my csv file if this helps:

BIRITE,130405,Steak Sauce,Kraft,24,5oz,43.96,1.83
BIRITE,441045,Anchovy Filet,Maria,12,13oz,51.83,4.32
2
I'm not using this to actually create valid code, just snippets that I can put into a larger file so I don't have to do it by hand. Difficult to explain in this context, but an xml parser is unnecessary at the moment. - Eric Amorde
Yeah IDK why I changed it here but in my code I used "with open as." And changing the method to just "return string" makes it behave as normal.. I don't get why though. I'll edit my question to include everything. - Eric Amorde
Okay, after for line in csvfile:, add print len(line.split(',')), repr(line[-5:]). Maybe (as I hinted earlier) the line endings aren't what you think they are, and so it's getting the entire thing in one line. - DSM
As @DSM is hinting, this is probably a file encoding problem. Can you show the output of head -2 input.csv | xxd ? - David Pope
Try replace your open call with open("input.csv","U") - Winston Ewert

2 Answers

3
votes

Use open('input.csv', "U") to open the file.

The "U" tells python to use the universal newlines feature. This allows python to automatically detect what kind of newlines are being used. The problem is that different platforms do newlines differently.

You may want to figure out why you've got strange newlines. You can easily work around the issue here but it could come back and be a pain later.

1
votes

NB: Done on a Linux Machine

Since this code seems to run for other people, lets create a CSV and then run the same code again on it, which shall clarify if it is an encoding issue.

a=open('test.csv','wb')
a.write("BIRITE,130405,Steak Sauce,Kraft,24,5oz,43.96,1.83\n"+
    "BIRITE,441045,Anchovy Filet,Maria,12,13oz,51.83,4.32\n")
a.close()

def string_to_xml(string):
    entries = string.split(',')
    result = "<item>\n"
    result += "\t<distributor>" + entries[0] + "</distributor>\n"
    result += "\t<number>" + entries[1] + "</number>\n"
    result += "\t<description>" + entries[2] + "</description>\n"
    result += "\t<brand>" + entries[3] + "</brand>\n"
    result += "\t<casesize>" + entries[4] + "</casesize>\n"
    result += "\t<unitsize>" + entries[5] + "</unitsize>\n"
    result += "\t<caseprice>" + entries[6] + "</caseprice>\n"
    result += "\t<unitprice>" + entries[7] + "</unitprice>\n"
    result += "</item>"
    return result

with open("test.csv") as csvfile:
    for line in csvfile:
       print string_to_xml(line)

And the output printed is:

<item>
<distributor>BIRITE</distributor>
<number>130405</number>
<description>Steak Sauce</description>
<brand>Kraft</brand>
<casesize>24</casesize>
<unitsize>5oz</unitsize>
<caseprice>43.96</caseprice>
<unitprice>1.83</unitprice>
</item>
<item>
<distributor>BIRITE</distributor>
<number>441045</number>
<description>Anchovy Filet</description>
<brand>Maria</brand>
<casesize>12</casesize>
<unitsize>13oz</unitsize>
<caseprice>51.83</caseprice>
<unitprice>4.32</unitprice>
</item>