Как обычно, чтобы продемонстрировать различные подходы к XML, я собираюсь взять полностью надуманный и возмутительный сценарий, и в этом сценарии вы работаете в Pete’s Perfect Pizza 1 , который является небольшим магазином на главной улице, но У Пита большие идеи, и первое, что он хочет сделать, — это автоматически отправлять заказы со стойки регистрации на кухню, и он просит вас написать код. Ваша большая идея — использовать XML для этого, и вы поспешно набросали свою идею на клочке бумаги и согласились с Питом …
1
2
3
4
5
6
|
<? xml version = '1.0' encoding = 'UTF-8' ?> < pizza > < name >Capricciosa</ name > < base >thin</ base > < quantity >2</ quantity > </ pizza > |
Pete’s — очень маленькая компания, и вы в конечном итоге кодируете как конструктор сообщений на стойке регистрации, так и код парсера XML для кухни. Это ваша первая попытка XML и кода парсера кухни, который вы придумали:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
public class OrderPizza { private String pizzaName; private String base; private String quantity; public void order(String xmlOrder) { pizzaName = xmlOrder.substring( 57 , xmlOrder.indexOf( '</' , 58 )); int index = xmlOrder.indexOf( '<base>' , 58 ); int index2 = xmlOrder.indexOf( '</' , index); base = xmlOrder.substring(index + 6 , index2); index = xmlOrder.indexOf( '<quantity>' , index2); index2 = xmlOrder.indexOf( '</' , index); quantity = xmlOrder.substring(index + 10 , index2); } public String getPizzaName() { return pizzaName; } public String getBase() { return base; } public String getQuantity() { return quantity; } } |
… который очень хорошо работает в ваших юнит-тестах:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
public class OrderPizzaTest { private static final String ORDER_XML = // '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n' + // '<pizza>\n' + // ' <name>Capricciosa</name>\n' + // ' <base>thin</base>\n' + // ' <quantity>2</quantity>\n' + // '</pizza>\n' ; private OrderPizza instance; @Before public void setUp() throws Exception { instance = new OrderPizza(); } @Test public void readOrderFromXML() { instance.order(ORDER_XML); assertEquals( 'Capricciosa' , instance.getPizzaName()); assertEquals( 'thin' , instance.getBase()); assertEquals( '2' , instance.getQuantity()); } } |
Это идет вживую и все хорошо ….
Время идет, и идеальная пицца Пита начинает расширяться. Приложение на стойке требует нескольких настроек, и Пит получает другого разработчика. Первое, что делает новый разработчик, — это решает, что было бы эффективнее избавиться от пробелов в XML-сообщении и отправил кухонному коду что-то вроде этого:
1
|
<? xml version = '1.0' encoding = 'UTF-8' ?>< pizza >< name >Capricciosa</ name >< base >thin</ base >< quantity >2</ quantity ></ pizza > |
Кухонный код мгновенно падает, и вы понимаете, что совершили первую и самую фундаментальную ошибку при работе с XML, то есть XML НЕ СТРОКА. XML — это объектно-ориентированная модель документа, которая может быть отображена с использованием строкового представления — урок, который многие люди усваивают сложным путем. И это не просто красивая печать строки, которая может сбить вас с толку, есть целая куча махинаций, форматирующих документы. Взять, к примеру, www.sitemaps.org. Этот веб-сайт определяет XML-схему, которая поддерживается Google, Yahoo !, и Microsoft, и позволяет веб-мастерам информировать поисковые системы о страницах на своих сайтах, доступных для сканирования с использованием XML-документа. Учитывая использование пространств имен в схеме, веб-сайт может возвращать что-то вроде этого, когда его просят о его карте сайта:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
<? xml version = '1.0' encoding = 'UTF-8' ?> xsi:schemaLocation = 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd' > < url > < lastmod >2005-01-01</ lastmod > < changefreq >monthly</ changefreq > < priority >0.8</ priority > </ url > < url > < lastmod >2006-01-02</ lastmod > < changefreq >weekly</ changefreq > < priority >0.8</ priority > </ url > </ urlset > |
… но он мог бы в равной степени вернуть это:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
<? xml version = '1.0' encoding = 'UTF-8' ?> xsi:schemaLocation = 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd' > < sm:url > < sm:lastmod >2005-01-01</ sm:lastmod > < sm:changefreq >monthly</ sm:changefreq > < sm:priority >0.8</ sm:priority > </ sm:url > < sm:url > < sm:lastmod >2006-01-02</ sm:lastmod > < sm:changefreq >weekly</ sm:changefreq > < sm:priority >0.8</ sm:priority > </ sm:url > </ sm:urlset > |
…или это:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
<? xml version = '1.0' encoding = 'UTF-8' ?> xsi:schemaLocation = 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd' > < sitemap:url > < sitemap:lastmod >2005-01-01</ sitemap:lastmod > < sitemap:changefreq >monthly</ sitemap:changefreq > < sitemap:priority >0.8</ sitemap:priority > </ sitemap:url > < sitemap:url > < sitemap:lastmod >2006-01-02</ sitemap:lastmod > < sitemap:changefreq >weekly</ sitemap:changefreq > < sitemap:priority >0.8</ sitemap:priority > </ sitemap:url > </ sitemap:urlset > |
… и все они действительны, эквивалентны и содержат одинаковую информацию. Это только их строковое представление, которые отличаются и взятые вместе, они подчеркивают первое правило XML, а именно XML НЕ СТРОКА.
Вернитесь к идеальной пицце Пита, и вы задаетесь вопросом, как вы можете исправить свой код, когда входит Пит и просит улучшения. Он хочет, чтобы вы улучшили систему, чтобы ваш XML-документ мог заказать более одной пиццы за раз. Вы понимаете, что манипулирование строками отсутствует и сталкиваетесь с SAX-анализом в Интернете, но об этом в другой раз.
1 Используя Google, вы обнаружите, что Pete’s Perfect Pizza со всего мира насчитывает четыре страницы. Эта история вымышленная, и любое сходство с любым из них является чисто совпадением.
2 Из прочтения XML-заказов вы можете догадаться, что моя любимая пицца — Capricciosa, и лучшая из всех, что когда-либо была доступна от Pizza Margherita
Исходный код доступен на GitHub по адресу:
мерзавец: //github.com/roghughe/captaindebug.git
Перейдите к части 2 серии.
Ссылка: Подходы к XML — Часть 1 — XML не является строкой … от нашего партнера по JCG Роджера Хьюза из блога Captain Debug’s Blog .