Различия
Здесь показаны различия между двумя версиями данной страницы.
Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
fullcircle:36:python_ч_10 [2010/08/07 21:11] |
fullcircle:36:python_ч_10 [2011/02/20 16:27] (текущий) |
||
---|---|---|---|
Строка 3: | Строка 3: | ||
//Автор — Грэг Валтерс (Greg Walters)// | //Автор — Грэг Валтерс (Greg Walters)// | ||
</style> | </style> | ||
+ | |||
- [[..:27:python_ч_1|Программа на Python — часть 1]] | - [[..:27:python_ч_1|Программа на Python — часть 1]] | ||
Строка 15: | Строка 16: | ||
- [[..:36:python_ч_10|Программа на Python — часть 10]] | - [[..:36:python_ч_10|Программа на Python — часть 10]] | ||
- [[..:37:python_ч_11|Программа на Python — часть 11]] | - [[..:37:python_ч_11|Программа на Python — часть 11]] | ||
+ | - [[..:38:python_ч_12|Программа на Python — часть 12]] | ||
+ | - [[..:39:python_ч_13|Программа на Python — часть 13]] | ||
+ | - [[..:40:python_ч_14|Программа на Python — часть 14]] | ||
Возможно, вы слышали об XML, однако можете и не знать, что это такое. В этом месяце нашу лекцию мы посвятим XML. Цели лекции: | Возможно, вы слышали об XML, однако можете и не знать, что это такое. В этом месяце нашу лекцию мы посвятим XML. Цели лекции: | ||
Строка 38: | Строка 42: | ||
<root><node1> Данные… </node1><node2 attribute=«something»> Данные Узла 2 </node2><node3><node3sub1>ещё данные</node3sub1></node3></root> | <root><node1> Данные… </node1><node2 attribute=«something»> Данные Узла 2 </node2><node3><node3sub1>ещё данные</node3sub1></node3></root> | ||
- | Тэги внутри угловых скобок «< >» отвечают некоторым правилам. Они должны состоять из одного слова. Каждому открывающему тэгу (например, <root>) должен соответствовать закрывающий, начинающийся с «/». Кроме того, тэги чувствительны к регистру: <node>, <Node>, <NODE> и <NodE> – различны, и к каждому из них должен быть свой закрывающий тэг. Наименования тэгов могут содержать буквы, цифры и другие символы, но не могут начинаться с цифры или знака препинания. Избегайте знаков «-», «.», «:» в именах тэгов, так как некоторые программы могут рассматривать их как команды или свойства объекта. Помимо этого, запятые зарезервированы для некоторых других целей. Тэги также можно называть элементами. | + | Тэги внутри угловых скобок **«< >»** отвечают некоторым правилам. Они должны состоять из одного слова. Каждому открывающему тэгу (например, <root>) должен соответствовать закрывающий, начинающийся с **«/»**. **Кроме того, тэги чувствительны к регистру: <node>, <Node>, <NODE> и <NodE> – различны**, и к каждому из них должен быть свой закрывающий тэг. Наименования тэгов могут содержать буквы, цифры и другие символы, но не могут начинаться с цифры или знака препинания. Избегайте знаков «-», «.», «:» в именах тэгов, так как некоторые программы могут рассматривать их как команды или свойства объекта. Помимо этого, запятые зарезервированы для некоторых других целей. Тэги также можно называть элементами. |
Каждый XML-файл – это древовидная структура, начинающаяся с корня и ответвляющаяся от него. Он ДОЛЖЕН иметь корневой элемент – родитель для всех других элементов в файле. Вернёмся к нашему примеру. От корня отходят три дочерних элемента: node1, node2 и node3. Дочерние элементы имеют общий корень, а node3 является родителем для node3sub1. | Каждый XML-файл – это древовидная структура, начинающаяся с корня и ответвляющаяся от него. Он ДОЛЖЕН иметь корневой элемент – родитель для всех других элементов в файле. Вернёмся к нашему примеру. От корня отходят три дочерних элемента: node1, node2 и node3. Дочерние элементы имеют общий корень, а node3 является родителем для node3sub1. | ||
Строка 48: | Строка 52: | ||
Имеется корневой элемент «people», содержащий два дочерних – «person». Каждый элемент «person» содержит 6 дочерних элементов: «firstname», «lastname», «gender», «address», «city» и «state». На первый взгляд, XML-файл можно рассматривать как базу данных (вспомните несколько последних лекций), и это верное предположение. Некоторые приложения используют XML-файлы как простую структуру базы данных. Не составит труда написать программу для чтения XML-файла. Она должна открыть файл, прочитать его построчно и, в зависимости от элемента, использовать заключённые в нём данные, а затем закрыть файл. Однако есть и более эффективные способы. | Имеется корневой элемент «people», содержащий два дочерних – «person». Каждый элемент «person» содержит 6 дочерних элементов: «firstname», «lastname», «gender», «address», «city» и «state». На первый взгляд, XML-файл можно рассматривать как базу данных (вспомните несколько последних лекций), и это верное предположение. Некоторые приложения используют XML-файлы как простую структуру базы данных. Не составит труда написать программу для чтения XML-файла. Она должна открыть файл, прочитать его построчно и, в зависимости от элемента, использовать заключённые в нём данные, а затем закрыть файл. Однако есть и более эффективные способы. | ||
- | В следующем примере мы воспользуемся модулем библиотеки под названием ElementTree. Его можно получить непосредственно из Synaptic, установив python-elementtree. Однако я предпочитаю устанавливать с сайта ElementTree (http://effbot.org/ downloads/#elementtree) и непосредственно загружать файл-исходник (elementtree-1.2.6-20050316.tar.gz). После загрузки я с помощью менеджера пакетов извлекаю его во временную папку. Затем в этой папке выполняю «sudo python setup.py install». Эта команда помещает файлы в общую папку python, поэтому в дальнейшем у меня есть возможность использовать модуль и в python 2.5, и в 2.6. Итак, приступим к работе! Создайте папку, которая будет содержать код этого месяца, скопируйте приведённые выше данные в XML-формате в ваш любимый текстовой редактор и сохраните их в эту папку под именем «xmlsample1.xml». | + | В следующем примере мы воспользуемся модулем библиотеки под названием ElementTree. Его можно получить непосредственно из Synaptic, установив python-elementtree. Однако я предпочитаю устанавливать с сайта ElementTree (http://effbot.org/downloads/#elementtree) и непосредственно загружать файл-исходник (elementtree-1.2.6-20050316.tar.gz). После загрузки я с помощью менеджера пакетов извлекаю его во временную папку. Затем в этой папке выполняю «sudo python setup.py install». Эта команда помещает файлы в общую папку python, поэтому в дальнейшем у меня есть возможность использовать модуль и в python 2.5, и в 2.6. Итак, приступим к работе! Создайте папку, которая будет содержать код этого месяца, скопируйте приведённые выше данные в XML-формате в ваш любимый текстовой редактор и сохраните их в эту папку под именем «xmlsample1.xml». |
Поговорим о нашем коде. В первую очередь хочется протестировать установленный модуль ElementTree. | Поговорим о нашем коде. В первую очередь хочется протестировать установленный модуль ElementTree. | ||
- | import elementtree.ElementTree as ET | + | <code>import elementtree.ElementTree as ET |
tree = ET.parse('xmlsample1.xml') | tree = ET.parse('xmlsample1.xml') | ||
- | ET.dump(tree) | + | ET.dump(tree)</code> |
Запустив эту программу, мы получим нечто похожее на то, что представлено ниже. | Запустив эту программу, мы получим нечто похожее на то, что представлено ниже. | ||
Строка 64: | Строка 68: | ||
Теперь заменим наш код на следующий: | Теперь заменим наш код на следующий: | ||
- | import elementtree.ElementTree as ET | + | <code>import elementtree.ElementTree as ET |
tree = ET.parse('xmlsample1.xml') | tree = ET.parse('xmlsample1.xml') | ||
Строка 74: | Строка 78: | ||
for dat in p: | for dat in p: | ||
- | print "Элемент: %s - Данные: %s" %(dat.tag,dat.text) | + | print "Элемент: %s - Данные: %s" %(dat.tag,dat.text)</code> |
Запустите код снова. Результат будет таким: | Запустите код снова. Результат будет таким: | ||
- | /usr/bin/python -u "/home/greg/Documents/articles/xml/reader1.py" | + | **/usr/bin/python -u "/home/greg/Documents/articles/xml/reader1.py"** |
- | Элемент: firstname - Данные: Саманта | + | * Элемент: firstname - Данные: Саманта |
- | Элемент: lastname - Данные: Фэроу | + | * Элемент: lastname - Данные: Фэроу |
- | Элемент: gender - Данные: Женский | + | * Элемент: gender - Данные: Женский |
- | Элемент: address - Данные: ул. Мэйн, д. 123 | + | * Элемент: address - Данные: ул. Мэйн, д. 123 |
- | Элемент: city - Данные: Дэнвер | + | * Элемент: city - Данные: Дэнвер |
- | Элемент: state - Данные: Колорадо | + | * Элемент: state - Данные: Колорадо |
- | Элемент: firstname - Данные: Стив | + | * Элемент: firstname - Данные: Стив |
- | Элемент: lastname - Данные: Левон | + | * Элемент: lastname - Данные: Левон |
- | Элемент: gender - Данные: Мужской | + | * Элемент: gender - Данные: Мужской |
- | Элемент: address - Данные: Бульвар Арапахо, 332120 | + | * Элемент: address - Данные: Бульвар Арапахо, 332120 |
- | Элемент: city - Данные: Дэнвер | + | * Элемент: city - Данные: Дэнвер |
- | Элемент: state - Данные: Колорадо | + | * Элемент: state - Данные: Колорадо |
Теперь каждая порция данных выводится напротив имени тэга. Эти данные можно легко распечатать. Итак, посмотрим, что делает программа. Модуль ElementTree проанализировал файл и поместил результаты в объект tree. Затем ElementTree нашёл все вхождения тэга person. В нашем примере таких элементов оказалось два, но их могло быть 1 или 1000. Элемент person – дочерний к корневому элементу people. Все данные были разбиты на порции. Затем мы создали простой цикл, перебирающий объекты person. Вложенный в него цикл перебирает данные каждого элемента person, и на экран выводятся результаты, показывающие имя элемента (.tag) и данные (.text). | Теперь каждая порция данных выводится напротив имени тэга. Эти данные можно легко распечатать. Итак, посмотрим, что делает программа. Модуль ElementTree проанализировал файл и поместил результаты в объект tree. Затем ElementTree нашёл все вхождения тэга person. В нашем примере таких элементов оказалось два, но их могло быть 1 или 1000. Элемент person – дочерний к корневому элементу people. Все данные были разбиты на порции. Затем мы создали простой цикл, перебирающий объекты person. Вложенный в него цикл перебирает данные каждого элемента person, и на экран выводятся результаты, показывающие имя элемента (.tag) и данные (.text). | ||
Строка 105: | Строка 109: | ||
Первая строка обычно сообщает, что это проверенный XML-файл, её можно проигнорировать. Следующая строка, начинающаяся с «loc», является корневым элементом и содержит атрибуты «version» и «src». Выше я отмечал, что атрибуты иногда используются в файлах. В дальнейшем мы ещё будем иметь дело с ними в этом файле. Корневой элемент тут также может быть проигнорирован. Следующая строка содержит тэг дочернего элемента – маршрутной точки (waypoint). (Маршрутная точка – это место расположения, где можно найти тайник). Из этого элемента можно получить важные сведения: наименование тайника, координаты (долготу и широту), тип тайника и ссылку на интернет-страницу с дополнительной информацией. Элемент с именем содержит кучу полезной информации, но проводить её структурный анализ придётся самостоятельно. Давайте теперь создадим программу для чтения и отображения файла cache.loc, назвав её readacache.py. Начнём с импорта модуля и команд для структурного анализа из предыдущего примера. | Первая строка обычно сообщает, что это проверенный XML-файл, её можно проигнорировать. Следующая строка, начинающаяся с «loc», является корневым элементом и содержит атрибуты «version» и «src». Выше я отмечал, что атрибуты иногда используются в файлах. В дальнейшем мы ещё будем иметь дело с ними в этом файле. Корневой элемент тут также может быть проигнорирован. Следующая строка содержит тэг дочернего элемента – маршрутной точки (waypoint). (Маршрутная точка – это место расположения, где можно найти тайник). Из этого элемента можно получить важные сведения: наименование тайника, координаты (долготу и широту), тип тайника и ссылку на интернет-страницу с дополнительной информацией. Элемент с именем содержит кучу полезной информации, но проводить её структурный анализ придётся самостоятельно. Давайте теперь создадим программу для чтения и отображения файла cache.loc, назвав её readacache.py. Начнём с импорта модуля и команд для структурного анализа из предыдущего примера. | ||
- | import elementtree.ElementTree as ET | + | <code>import elementtree.ElementTree as ET |
- | tree = ET.parse('Cache.loc') | + | tree = ET.parse('Cache.loc')</code> |
Нам необходимо получить только данные, находящиеся внутри тэга waypoint. Для этого мы используем функцию .find внутри модуля ElementTree. Результаты работы будут сохранены в объекте w. | Нам необходимо получить только данные, находящиеся внутри тэга waypoint. Для этого мы используем функцию .find внутри модуля ElementTree. Результаты работы будут сохранены в объекте w. | ||
- | w = tree.find('.//waypoint') | + | <code>w = tree.find('.//waypoint')</code> |
Затем нам необходимо просмотреть все данные, для чего используется цикл for. В теле цикла мы ищем элементы name (имя), coord (координаты), type (тип) и link (ссылка). На основании содержащихся в тэге данных, мы извлекаем информацию, чтобы распечатать её в дальнейшем. | Затем нам необходимо просмотреть все данные, для чего используется цикл for. В теле цикла мы ищем элементы name (имя), coord (координаты), type (тип) и link (ссылка). На основании содержащихся в тэге данных, мы извлекаем информацию, чтобы распечатать её в дальнейшем. | ||
- | for w1 in w: | + | <code>for w1 in w: |
- | if w1.tag == "name": | + | if w1.tag == "name":</code> |
Просмотрим, какие данные можно извлечь из тэга name. | Просмотрим, какие данные можно извлечь из тэга name. | ||
- | + | <code> | |
- | <name id="N02CAC"><![CDATA[Возьмите Фотографии озера Виноградной лозы, сделанные g_phillips | + | <name id="N02CAC"><![CDATA[Возьмите Фотографии озера |
+ | Виноградной лозы, сделанные g_phillips | ||
Тайник открыт: не ограничено | Тайник открыт: не ограничено | ||
Строка 131: | Строка 136: | ||
Местность: 2.0]]></name> | Местность: 2.0]]></name> | ||
+ | </code> | ||
Это одна очень длинная строка. Идентификатор id установлен как атрибут. Имя тайника – это часть строки после «CDATA» и до «Тайник открыт:». Мы разделим | Это одна очень длинная строка. Идентификатор id установлен как атрибут. Имя тайника – это часть строки после «CDATA» и до «Тайник открыт:». Мы разделим | ||
- | строку на несколько более мелких частей. Получить часть строки можно, используя следующий код: | + | строку на несколько более мелких частей. |
- | + | ||
- | newstring = oldstring[startposition:endposition] | + | <code>newstring = oldstring[startposition:endposition]</code> |
Итак, приведенный код можно использовать для извлечения необходимой информации. | Итак, приведенный код можно использовать для извлечения необходимой информации. | ||
Строка 205: | Строка 208: | ||
<loc version="1.0" src="NaviCache"> | <loc version="1.0" src="NaviCache"> | ||
<waypoint> | <waypoint> | ||
- | <name id="N02CAC"><![CDATA[Take Goofy Pictures at Grapevine Lake by g_phillips | + | <name id="N02CAC"><![CDATA[Take Goofy |
+ | Pictures at Grapevine Lake by g_phillips | ||
Open Cache: Unrestricted | Open Cache: Unrestricted | ||
Cache Type: Normal | Cache Type: Normal | ||
Строка 213: | Строка 217: | ||
<coord lat="32.9890166666667" lon="-97.0728833333333" /> | <coord lat="32.9890166666667" lon="-97.0728833333333" /> | ||
<type>Geocache</type> | <type>Geocache</type> | ||
- | <link text="Cache Details">http://www.navicache.com/cgi-bin/db/displaycache2.pl?CacheID=11436</link> | + | <link |
+ | text="Cache Details"> | ||
+ | http://www.navicache.com/cgi-bin/db/displaycache2.pl | ||
+ | ?CacheID=11436</link> | ||
</waypoint> | </waypoint> | ||
</loc> | </loc> | ||
Строка 221: | Строка 228: | ||
<code> | <code> | ||
# Get text of cache name up to the phrase "Open Cache: " | # Get text of cache name up to the phrase "Open Cache: " | ||
- | CacheName = w1.text[:w1.text.find("Open Cache: ")-1] | + | CacheName = w1.text[:w1.text.find |
+ | ("Open Cache: ")-1] | ||
# Get the text between "Open Cache: " and "Cache Type: " | # Get the text between "Open Cache: " and "Cache Type: " | ||
- | OpenCache = w1.text[w1.text.find("Open Cache: ")+12:w1.text.find("Cache Type: ")-1] | + | OpenCache = w1.text[w1.text.find |
+ | ("Open Cache: ")+12:w1.text.find("Cache Type: ")-1] | ||
# More of the same | # More of the same | ||
- | CacheType = w1.text[w1.text.find("Cache Type: ")+12:w1.text.find("Cache Size: ")-1] | + | CacheType = w1.text[w1.text.find |
- | CacheSize = w1.text[w1.text.find("Cache Size: ")+12:w1.text.find("Difficulty: ")-1] | + | ("Cache Type: ")+12:w1.text.find |
- | Difficulty= w1.text[w1.text.find("Difficulty: ")+12:w1.text.find("Terrain : ")-1] | + | ("Cache Size: ")-1] |
- | Terrain = w1.text[w1.text.find("Terrain : ")+12:] | + | CacheSize = w1.text[w1.text.find |
+ | ("Cache Size: ")+12:w1.text.find | ||
+ | ("Difficulty: ")-1] | ||
+ | Difficulty= w1.text[w1.text.find | ||
+ | ("Difficulty: ")+12:w1.text.find | ||
+ | ("Terrain : ")-1] | ||
+ | Terrain = w1.text[w1.text.find | ||
+ | ("Terrain : ")+12:] | ||
</code> | </code> | ||
Строка 269: | Строка 285: | ||
if w1.tag == "name": | if w1.tag == "name": | ||
# Get text of cache name up to the phrase "Open Cache: " | # Get text of cache name up to the phrase "Open Cache: " | ||
- | CacheName = w1.text[:w1.text.find("Open Cache: ")-1] | + | CacheName = w1.text[:w1.text.find |
- | # Get the text between "Open Cache: " and "Cache Type: " | + | ("Open Cache: ")-1] |
- | OpenCache = w1.text[w1.text.find("Open Cache: ")+12:w1.text.find("Cache Type: ")-1] | + | # Get the text between |
+ | "Open Cache: " and "Cache Type: " | ||
+ | OpenCache = w1.text[w1.text.find | ||
+ | ("Open Cache: ")+12:w1.text.find | ||
+ | ("Cache Type: ")-1] | ||
# More of the same | # More of the same | ||
- | CacheType = w1.text[w1.text.find("Cache Type: ")+12:w1.text.find("Cache Size: ")-1] | + | CacheType = w1.text[w1.text.find |
- | CacheSize = w1.text[w1.text.find("Cache Size: ")+12:w1.text.find("Difficulty: ")-1] | + | ("Cache Type: ")+12:w1.text.find |
- | Difficulty= w1.text[w1.text.find("Difficulty: ")+12:w1.text.find("Terrain : ")-1] | + | ("Cache Size: ")-1] |
- | Terrain = w1.text[w1.text.find("Terrain : ")+12:] | + | CacheSize = w1.text[w1.text.find |
+ | ("Cache Size: ")+12:w1.text.find | ||
+ | ("Difficulty: ")-1] | ||
+ | Difficulty= w1.text[w1.text.find | ||
+ | ("Difficulty: ")+12:w1.text.find | ||
+ | ("Terrain : ")-1] | ||
+ | Terrain = w1.text[w1.text.find | ||
+ | ("Terrain : ")+12:] | ||
if w1.keys(): | if w1.keys(): | ||
for name,value in w1.items(): | for name,value in w1.items(): |