Python,读取/写入文档时未知的跳过

时间:2012-08-11 08:56:57

标签: python xml

所以我使用python来帮助将文本文件更改为xml。以下文本文件的索姆文。

:
Breakfast Breads

Gluten Free Nut Loaf
Makes 1 loaf

150 g (51/2 oz./11/2 cups) 
almond meal
30 g (1 oz./1/4 cup)
walnuts, coarsely chopped
1/4 teaspoon 
gluten-free baking powder

我不确定这是否可以复制,因为它可能是文件本身的一个幽灵。但如果你能尝试那就太好了。

为了解释当前的步骤,我的代码很简陋,寻找冒号,它知道下一行是一般类别,然后切换一个步骤变量。然后下一步将跳过空行' \ r \ n'直到它找到一个非空行,用它的名字来标识单个食谱的开头。循环中的下一行,如果为空更改步骤,则为服务大小写入xml然后更改步骤。

这里我们到达成分步骤。所以奇数行是数量,偶数行是实际成分。

if step == 2:
    if line == empty: 
        continue
    else:
        xmlMenu.write("\n\t<ingredients>") 
        qty = line
        qtyXML = ("\n\t\t<qty>\n\t\t\t" + qty + "\t\t</qty>")
        xmlMenu.write(qtyXML)
        step = 2.2
        continue

if step == 2.2:
        if menu.next() == empty:
            ingredient = line
            pass
            ingredientXML = ("\n\t\t<ingredient>\n\t\t\t" + ingredient + "\t\t</ingredient>\n\t</ingredients>")
            xmlMenu.write(ingredientXML)
            step = 3
            continue

        else:
            ingredient = line
            ingredientXML = ("\n\t\t<ingredient>\n\t\t\t" + ingredient + "\t\t</ingredient>\n\t</ingredients>")
            xmlMenu.write(ingredientXML)
            step = 2
            continue

我的问题是,当它到达第二组数量/成分时,它似乎跳过了杏仁粉的数量,因此搞砸了整个xml文件。

<recipe>
    <category>
        Breakfast Breads
    </category>
    <name>
        Gluten Free Nut Loaf
    </name>
    <servings>
        Makes 1 loaf
    </servings>
    <ingredients>
        <qty>
            150 g (51/2 oz./11/2 cups) 
        </qty>
        <ingredient>
            almond meal
        </ingredient>
    </ingredients>
    <ingredients>
        <qty>
            walnuts, coarsely chopped
        </qty>
        <ingredient>
            1/4 teaspoon 
        </ingredient>
    </ingredients>

如果我的代码只是废话,任何人都有任何想法?此外,任何建议更好的方法来做到这一点。我还是初级程序设计。

//编辑更多代码。当代码开始新配方时,代码仍然在工作结束时工作。

empty = '\r\n'
colon = ':'
new_contents = []

category = ''
categoryXML = ''

recipe = ''
recipeXML = ''

servings = ''
servingsXML = ''

ingrediants = ''
ingrediantsXML = ''

ingredient = ''
ingredientXML = ''
qty = ''
qtyXML = ''

instructions = ''
instructionsXML = ''

intNo = ''
intNoXML = ''
instruction = ''
instructionXML = ''

step = ''

x = 0

menu = open("menuTextFormat.txt", 'r')
xmlMenu = open('menuTextXML.txt', 'w')

for line in menu:
    # if not line.strip():
    #    continue
    #else:
    #     new_contents.append(line)
    if colon in line:
        step = 0
        continue

    if step == 0: 
        if not line:
            continue 
        else:       
            category = line
            categoryXML = "<recipe>\n\t<category>\n\t\t" + category + "\t</category>"
            xmlMenu.write(categoryXML)    
            step = 1            
            continue

    if step == 1:
        if line == empty:
            continue 
        else:
            recipe = line
            recipeXML = ("\n\t<name>\n\t\t" + recipe + "\t</name>")
            xmlMenu.write(recipeXML)
            step = 12
            continue

    if step == 12:
        if line == empty:
            step = 2
            continue
        else: 
            servings = line
            servingsXML = ("\n\t<servings>\n\t\t" + servings + "\t</servings>")
            xmlMenu.write(servingsXML)
            step = 2

            continue

    if step == 2:
        if line == empty: 
            continue
        else:
            xmlMenu.write("\n\t<ingredients>") 
            qty = line
            qtyXML = ("\n\t\t<qty>\n\t\t\t" + qty + "\t\t</qty>")
            xmlMenu.write(qtyXML)
            step = 22
            continue

    if step == 22:
            if menu.next() == empty:
                ingredient = line
                ingredientXML = ("\n\t\t<ingredient>\n\t\t\t" + ingredient + "\t\t</ingredient>\n\t</ingredients>")
                xmlMenu.write(ingredientXML)
                step = 3
                continue

            else:
                ingredient = line
                ingredientXML = ("\n\t\t<ingredient>\n\t\t\t" + ingredient + "\t\t</ingredient>\n\t</ingredients>")
                xmlMenu.write(ingredientXML)
                step = 2
                continue

    if step == 3:
        if line == empty:
            continue 
        else:
            x += 1
            intNoXML = ("\n\t\t<id>\n\t\t\t" + str(x) + "\n\t\t</id>")
            xmlMenu.write(intNoXML)
            instruction = line
            instructionXML = ("\n\t\t<instruction>\n\t\t\t" + instruction + "\t\t</instruction>")
            xmlMenu.write(instructionXML)
            if menu.next() == empty:
                step = 4
                continue
            else:
                continue
            continue

    if step == 4:
        if not menu.next():
            break
        else:
            step = 1
            continue


    #print line

#xmlMenu.write("".join(new_contents))


xmlMenu.close()
menu.close()


:
Breakfast Breads

Gluten Free Nut Loaf
Makes 1 loaf

150 g (51/2 oz./11/2 cups) 
almond meal
30 g (1 oz./1/4 cup)
walnuts, coarsely chopped
1/4 teaspoon 
gluten-free baking powder
1 teaspoon 
ground cinnamon
95 g (31/4 oz./3/4 cup) 
arrowroot (tapioca) flour
1/2 teaspoon 
sea salt
3 
organic eggs
1/2 teaspoon 
stevia powder
3 tablespoons 
grape seed oil
2 tablespoons 
coconut Milk
1 teaspoon 
apple cider vinegar

Preheat the oven to 180∫C (350∫F/Gas 4). 
Grease a 20 x 9 cm (8 x 31/2 inch) loaf (bar) tin.
Put the almond meal, walnuts, baking powder, cinnamon, arrowroot flour and salt in a large bowl and mix well with a wooden spoon. 
Crack the eggs into a separate bowl and whisk using an electric mixer until pale and fluffy, about 11/2 minutes. 
Add the stevia, grape seed oil, coconut milk and vinegar and mix gently. 
Pour the mixture into the dry ingredients and stir to combine. 
Spoon the mixture into the greased tin and bake for about 40 minutes, or until a skewer inserted in the centre of the loaf comes out clean. 
Remove the bread from the oven and leave to cool in the tin for a few minutes, before turning out onto a wire rack to cool completely. 
Enjoy the bread melt-in-the-mouth warm, or at room temperature with your favourite topping.  

Basic Gluten Free Loaf

2Ω cups 
blanched almond flour
Ω teaspoon 
baking soda
1 tsp. 
bicarbonate of soda
3 
eggs beaten
1 tsp. 
stevia powder
Ω teaspoon 
apple cider vinegar
!!
Pinch sea salt

Preheat oven to 250 degrees Celsius
Grease a small loaf pan
Combine dry ingredients in a bowl
In a separate bowl place eggs and apple cider vinegar
Spoon the mixture into loaf pan
Bake for 50 mins until set
Cool on wire rack
Slice when cool

更多数据。

2 个答案:

答案 0 :(得分:2)

如果将代码划分为每个函数只负责识别一个小特征的函数,则代码将更容易理解,例如:

def parse_next_receipe(lines, pos=0):
    while 1:
        if pos >= len(lines):
            break

        line = lines[pos]
        if line.strip() == ':':
            pos, receipe = parse_receipe(lines, pos)
            yield receipe  # or write it directly to the xml file...
        else:
            pos += 1

def parse_receipe(lines, pos):
    pos, name = parse_name(lines, pos)
    pos, description = parse_description(lines, pos)
    ingredients = []

    while 1:
        pos, ingredient = parse_ingredient(lines, pos)
        if pos == -1:
            break
        else:
            ingredients.append(ingredient)

    return (name, description, ingredients)


def parse_name(lines, pos): ...

def parse_description(lines, pos): ...

def parse_ingredient(lines, pos):
    try:
        pos, quantity = parse_quantity(lines, pos)
        pos, ingredient = parse_ingredientname(lines, pos)
    except ValueError:
        return -1, None

def parse_quantity(lines, pos):
    line = lines[pos]
    if line[0] in '0123456789':
        # line starts with a number
        return pos + 1, line
    raise ValueError("Line %r doesn't contain a quantity" % line)

def parse_ingredientname(lines, pos):
    line = lines[pos]
    if line:
        # any non-empty line is ok as an ingredient name
        return pos + 1, line
    raise ValueError("Expected an ingredient name, found blank line, lineno=%d" % pos)

这称为递归下降解析。

在该示例中,每个函数都使用pos这是它应该开始查看的行号,并返回“下一行”以查看它找到的值。

我使用了两种不同的方法来指示解析错误:将-1作为位置返回(并将None作为值),或者引发异常。任何一个都可能有用。

答案 1 :(得分:1)

你会发现一些事情......
我删除了你在循环之前列出的很多变量。你不需要在循环之前列出它们 我把它切换到了一个while循环。我个人喜欢能够一次读取一行的内容 3.我在名称部分编写了类别,这只是因为当新配方开始时并不总是列出类别,所以我认为最好使用最后一个已知的类别并在每个新的前面插入配方。
4.您的服务大小并不总是列出,所以我冒昧地在那里添加一张支票,以便以防万一的方式返回“未列出的服务大小”。
我在成分上使用了一个循环。

备注:
1.由于每and line if step == 1 and line:,所有空行都被完全忽略。变量line被删除所有行返回,因此while循环跳过所有新行。这些步骤只是确保我们在跳过每个空行后做正确的事情 坚果面包听起来很美味

<强>代码:

category=''
step=0

menu = open("menuTextFormat.txt", 'r')
xml = open('menuTextXML.txt', 'w')

xml.write("<recipe>\n")

while 1:
    line = menu.readline()
    if not line:
        break

    #after checking for EOF, remove \n
    line = line.rstrip()

    #category
    if ":" in line:
        #set category as next line
        category = menu.readline().rstrip()
        step=1
        continue

    #name & servings
    if step == 1 and line:
        #write category
        xml.write("\t<category>\n\t\t" + category + "\n\t</category>\n")
        #write name
        xml.write("\t<name>\n\t\t" + line + "\n\t</name>\n")

        #check for serving size
        servings = menu.readline().rstrip()
        if not servings:
            xml.write("\t<servings>\n\t\tno serving size listed\n\t</servings>\n")
        else:
            xml.write("\t<servings>\n\t\t" + servings + "\n\t</servings>\n")

        step=2
        continue

    #ingredients
    if step == 2 and line:
        #write first ingredient, then loop for rest
        xml.write("\t<qty>\n\t\t" + line + "\n\t</qty>\n")
        xml.write("\t<ingredient>\n\t\t" + menu.readline().rstrip() + "\n\t</ingredient>\n")

        #loop for incredients
        while 1:
            qty = menu.readline().rstrip()
            #no more incredients, break loop
            if not qty:
                break

            xml.write("\t<qty>\n\t\t" + qty + "\n\t</qty>\n")
            xml.write("\t<ingredient>\n\t\t" + menu.readline().rstrip() + "\n\t</ingredient>\n")

        step=3
        continue

    #procedure
    if step == 3 and line:
        #write first step, then loop for rest
        xml.write("\t<procedure>\n")
        xml.write("\t\t<step>\n\t\t\t" + line + "\n\t\t</step>\n")

        #loop for steps
        while 1:
            step = menu.readline().rstrip()
            #no more steps, break loop
            if not step:
                break

            xml.write("\t\t<step>\n\t\t\t" + step + "\n\t\t</step>\n")

        xml.write("\t</procedure>\n")

        step=1
        continue

xml.write("</recipe>")
menu.close()
xml.close()

<强>输出:

<recipe>
    <category>
        Breakfast Breads
    </category>
    <name>
        Gluten Free Nut Loaf
    </name>
    <servings>
        Makes 1 loaf
    </servings>
    <qty>
        150 g (51/2 oz./11/2 cups)
    </qty>
    <ingredient>
        almond meal
    </ingredient>
    <qty>
        30 g (1 oz./1/4 cup)
    </qty>
    <ingredient>
        walnuts, coarsely chopped
    </ingredient>
    <qty>
        1/4 teaspoon
    </qty>
    <ingredient>
        gluten-free baking powder
    </ingredient>
    <qty>
        1 teaspoon
    </qty>
    <ingredient>
        ground cinnamon
    </ingredient>
    <qty>
        95 g (31/4 oz./3/4 cup)
    </qty>
    <ingredient>
        arrowroot (tapioca) flour
    </ingredient>
    <qty>
        1/2 teaspoon
    </qty>
    <ingredient>
        sea salt
    </ingredient>
    <qty>
        3
    </qty>
    <ingredient>
        organic eggs
    </ingredient>
    <qty>
        1/2 teaspoon
    </qty>
    <ingredient>
        stevia powder
    </ingredient>
    <qty>
        3 tablespoons
    </qty>
    <ingredient>
        grape seed oil
    </ingredient>
    <qty>
        2 tablespoons
    </qty>
    <ingredient>
        coconut Milk
    </ingredient>
    <qty>
        1 teaspoon
    </qty>
    <ingredient>
        apple cider vinegar
    </ingredient>
    <procedure>
        <step>
            Preheat the oven to 180∫C (350∫F/Gas 4).
        </step>
        <step>
            Grease a 20 x 9 cm (8 x 31/2 inch) loaf (bar) tin.
        </step>
        <step>
            Put the almond meal, walnuts, baking powder, cinnamon, arrowroot flour and salt in a large bowl and mix well with a wooden spoon.
        </step>
        <step>
            Crack the eggs into a separate bowl and whisk using an electric mixer until pale and fluffy, about 11/2 minutes.
        </step>
        <step>
            Add the stevia, grape seed oil, coconut milk and vinegar and mix gently.
        </step>
        <step>
            Pour the mixture into the dry ingredients and stir to combine.
        </step>
        <step>
            Spoon the mixture into the greased tin and bake for about 40 minutes, or until a skewer inserted in the centre of the loaf comes out clean.
        </step>
        <step>
            Remove the bread from the oven and leave to cool in the tin for a few minutes, before turning out onto a wire rack to cool completely.
        </step>
        <step>
            Enjoy the bread melt-in-the-mouth warm, or at room temperature with your favourite topping.
        </step>
    </procedure>
    <category>
        Breakfast Breads
    </category>
    <name>
        Basic Gluten Free Loaf
    </name>
    <servings>
        no serving size listed
    </servings>
    <qty>
        2Ω cups
    </qty>
    <ingredient>
        blanched almond flour
    </ingredient>
    <qty>
        Ω teaspoon
    </qty>
    <ingredient>
        baking soda
    </ingredient>
    <qty>
        1 tsp.
    </qty>
    <ingredient>
        bicarbonate of soda
    </ingredient>
    <qty>
        3
    </qty>
    <ingredient>
        eggs beaten
    </ingredient>
    <qty>
        1 tsp.
    </qty>
    <ingredient>
        stevia powder
    </ingredient>
    <qty>
        Ω teaspoon
    </qty>
    <ingredient>
        apple cider vinegar
    </ingredient>
    <qty>
        !!
    </qty>
    <ingredient>
        Pinch sea salt
    </ingredient>
    <procedure>
        <step>
            Preheat oven to 250 degrees Celsius
        </step>
        <step>
            Grease a small loaf pan
        </step>
        <step>
            Combine dry ingredients in a bowl
        </step>
        <step>
            In a separate bowl place eggs and apple cider vinegar
        </step>
        <step>
            Spoon the mixture into loaf pan
        </step>
        <step>
            Bake for 50 mins until set
        </step>
        <step>
            Cool on wire rack
        </step>
        <step>
            Slice when cool
        </step>
    </procedure>
</recipe>