Używam Pythona, aby pomóc zmienić plik tekstowy do XML. Somme dokumentu tekstowego poniżej.

:
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

Nie jestem pewien, czy można to powtórzyć, ponieważ może to być duch w samym pliku. Ale jeśli mógłbyś spróbować, byłoby świetnie.

Aby wyjaśnić aktualne kroki, mój kod jest prymitywny, szukający okrężnicy, wie, że kolejna linia jest ogólną kategorią, a następnie przełącza zmienną krok. Następnie następny krok pomija puste linie "r n", dopóki nie znajdzie pustą linię, która zidentyfikowała początek indywidualnego receptury, ze swoją nazwą. Następny wiersz w pętli, jeśli pusty krok zmiany, w przeciwnym razie napisz XML do rozmiaru serwowania, a następnie zmień krok.

Tutaj osiągamy krok składników. Więc linie dziwne są qty, a nawet linie są rzeczywistym składnikiem.

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

Mój problem, gdy osiągnie drugi zestaw Ilość / składnika, pozornie pomija Ilość dla posiłku migdałowego, więc wkręca cały plik 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>

Czy ktoś ma jakieś myśli, jeśli mój kod jest gdzieś bzdurny? Ponadto wszelkie sugestie dotyczące lepszej metody. Nadal programowanie na poziomie początkującego.

// Edytuj, aby uzyskać więcej kodu. Kod nadal działa na końcu zestawu, gdy rozpoczyna nowy receptura.

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

Więcej danych.

0
Pete 11 sierpień 2012, 12:56

2 odpowiedzi

Najlepsza odpowiedź

Zauważysz kilka rzeczy ...
1. Usunąłem wiele zmiennych, które wymieniłeś przed pętlą. Naprawdę nie musisz ich wymienić przed pętlą.
2. Przełączałem go na chwilę pętli. Osobiście podoba mi się odwołanie do czytania rzeczy jedna linia na raz
3. Napisałem kategorię w sekcji Nazwa, jest to sprawa, że kategoria nie jest zawsze wymieniona, gdy rozpoczyna się nowa receptura, więc obowiązywam, że najlepiej byłoby korzystać z ostatniej znanej kategorii i włóż, że przed każdym nowym Receptura.
. 4. Rozmiar serwowania nie zawsze był wymieniony, więc wziąłem wolność dodawania tam zameldowania, więc powróciłoby "rozmiar serwowania, który nie ma na liście" na wszelki wypadek.
5. Użyłem pętli na składnikach.

Uwagi:
1. Wszystkie puste linie są całkowicie ignorowane z powodu and line w każdym if step == 1 and line:. Zmienna line jest pozbawiona wszystkich zwrotów linii, dzięki czemu pętla pomija wszystkie nowe linie. Kroki tylko upewnij się, że robimy właściwą rzecz po pominięciu każdej pustej linii.
2. Bochenek orzechów brzmi pyszny

Kod:

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()

Wynik:

<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>
1
Rawr 11 sierpień 2012, 11:11

Twój kod będzie łatwiej zrozumieć, jeśli podzielisz go w funkcje, w których każda funkcja jest odpowiedzialna za rozpoznanie tylko małej funkcji, np.:

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)

Nazywa się to ankietowaniem rekurencyjnego parsowania.

W przykładzie każda funkcja zajmuje pos, który jest numerem linii, w którym ma się rozpocząć, i zwraca linię "Dalej", aby spojrzeć na + wartość, którą znalazł.

Użyłem dwóch różnych metod wskazywania błędu analizowania: zwrócone {x0}} jako pozycja (i {x1}} jako wartość) lub podnoszenie wyjątku. Każdy może być przydatny.

2
thebjorn 11 sierpień 2012, 10:14