1. Define the Source XML (data.xml)
<dictionary>
<entry>
<word>Apple</word>
<definition>A round fruit with red or green skin.</definition>
<image>apple.jpg</image>
</entry>
<entry>
<word>Banana</word>
<definition>A long curved fruit with yellow skin.</definition>
<image>banana.jpg</image>
</entry>
</dictionary>
2. The Python Script
import xml.etree.ElementTree as ET
import genanki
import random
import hashlib
# 1. Define the Note Model (The Template)
# We use a hardcoded ID so the model stays consistent across runs.
def get_model_id():
return 1607392319
my_model = genanki.Model(
get_model_id(),
'Simple XML Vocabulary Model',
fields=[
'name': 'Word',
'name': 'Definition',
'name': 'Image', # Field for media
],
templates=[
'name': 'Card 1',
'qfmt': 'Word<br>Image', # Front of card
'afmt': 'FrontSide<hr id="answer">Definition', # Back of card
,
],
css='.card font-family: arial; font-size: 20px; text-align: center; color: black; background-color: white; '
)
# 2. Define the Deck
def get_deck_id():
return random.randrange(1 << 30, 1 << 31)
my_deck = genanki.Deck(
get_deck_id(),
'XML Imported Vocabulary'
)
# 3. Parse the XML
def parse_xml_and_populate_deck(xml_file, deck, model):
tree = ET.parse(xml_file)
root = tree.getroot()
# List to hold media files for packaging later
media_files = []
for entry in root.findall('entry'):
word = entry.find('word').text
definition = entry.find('definition').text
image_filename = entry.find('image').text
# Anki requires specific formatting for images in fields
# We construct the HTML string
image_html = f'<img src="image_filename">'
# Add image path to media list (assuming images are in the local directory)
media_files.append(image_filename)
# Create the Note
# genanki handles GUIDs automatically, but manual creation ensures stability
note = genanki.Note(
model=model,
fields=[word, definition, image_html]
)
deck.add_note(note)
return media_files
# 4. Execute and Package
media_files = parse_xml_and_populate_deck('data.xml', my_deck, my_model)
# Create the package
# If you have media, you pass them in the media_files list
my_package = genanki.Package(my_deck, media_files=media_files)
# Write to file
my_package.write_to_file('output.apkg')
print("Successfully created output.apkg")
Create xml_to_csv.xsl:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/cards">
<xsl:text>Question,Answer
</xsl:text>
<xsl:for-each select="card">
<xsl:value-of select="question"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="answer"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Run transformation (using Saxon or xsltproc): xml to apkg
xsltproc xml_to_csv.xsl input.xml > output.csv
pip install genanki
anki_url = "http://localhost:8765"
for item in root.findall('card'): note = "action": "addNote", "version": 6, "params": "note": "deckName": "MyXMLDeck", "modelName": "Basic", "fields": "Front": item.find('question').text, "Back": item.find('answer').text , "tags": ["xml_import"] requests.post(anki_url, data=json.dumps(note)) Create xml_to_csv
After execution, your cards appear instantly in Anki. You can then export as .apkg via the GUI. "params":
"note":
"deckName": "MyXMLDeck"