Не важно, в какую сторону вы склоняетесь в споре о DRM и свободном программном обеспечении — бесспорно, информация о нашем (американском) правительстве должна быть бесплатной. Чем больше граждане знают о правительстве, тем лучше. Как же использовать XML и семантический веб для облегчения доступа к этой информации и поощрения участия граждан?
В последние несколько лет я потратил много времени, размышляя над этим вопросом, при составлении www.GovTrack.us, сайта, собирающего захватывающую информацию о Конгрессе США и использующего новые технологии, такие как RSS и Google Maps. Появление сайта стало возможным, потому что правительство помещало в интернет информацию, но разбрасывало по разным сайтам. Например, законодательство размещается на одном сервере, а результаты голосований по тем же самым законам — на другом. Размещение информации на одном сайте и в одном формате позволяет по-новому комбинировать данные.
Каждый день GovTrack просматривает правительственные сайты в поисках новой информации, которая затем стандартизируется и помещается в XML-файлы, чтобы при запросе пользователя о состоянии законопроекта просто применить таблицу стилей XSLT к XML-файлу законопроекта.
С 1999 года через конгресс прошло около 40 500 законопроектов (большая часть серьёзно не была рассмотрена). Вот часть файла законопроекта, принятого 14 сентября 2001 года и разрешающего президенту использовать вооружённые силы для борьбы с террористами:
<bill session="107" type="sj" number="23">
<titles>
<title type="popular">Military Force Authorization
resolution</title>
<title type="official">A joint resolution to authorize
the use of United States Armed Forces against those
responsible for the recent attacks launched against
the United States.</title>
</titles>
<sponsor id="300031" />
<actions>
<vote date="1000440000" how="roll" roll="281" where="s"/>
<vote date="1000520280" how="without objection" where="h"/>
<enacted law="107-40" date="1000785600"/>
</actions>
<subjects>
<term name="Defense policy"/>
<term name="Air piracy"/>
<term name="Armed forces"/>
...
</subjects>
<summary>
Authorizes the President to use all necessary and
appropriate force...
</summary>
</bill>
Всё это доступно из официальных источников, но в официальных источниках информация не представлена в структурированном виде. GovTrack обрабатывает даты, преобразует названия в идентификаторы, выбирает список действий и так далее. Кроме того, GovTrack обрабатывает информацию о голосованиях и другие документы и преобразует в XML. (Кстати, если вы хотите немного поиграться с данными, все XML-файлы, используемые GovTrack, могут быть свободно использованы.)
XML хорошо подходил для данной задачи, но просто собрав много файлов XML вместе вы не получите ничего особенного — необходимо писать код. Таким образом, GovTrack получает возможность просмотра законопроектов по их тематике.
Но однажды я получил письмо с просьбой найти законы, подпадающие под несколько категорий. Для этого понадобился простой запрос к данным, который бы искал совпадения по обеим темам. Самым простым способом могло бы быть написание программы, обрабатывающей выражение XPath по каждому файлу законопроекта.
count(bill/subjects/term[@name = "Medical care"]) > 0
and count(bill/subjects/term[@name = "Illegal aliens"]) >
0
Конечно, этот способ выполнил бы поставленную задачу, но он очень ограничивает разнообразие запросов к данным. Выражение XPath может обрабатывать только один документ, то есть можно задавать лишь вопросы типа, соответствует ли документ выражению. Ответ на такой вопрос зависит только от документа. (Действительно, можно использовать функцию Document() для просмотра нескольких документов, но только в том случае, когда известны их имена.)
Если завтра кто-нибудь попросит у меня список документов, за которые Билл Фрист и Джон Керри голосовали по-разному, я окажусь в тупике. Каждый файл поимённого голосования выглядит примерно следующим образом:
<roll where="senate" year="2005" roll="00230">
<question>On the Motion (Motion To Table)</question>
<voter id="300001" vote="+"/>
<voter id="300002" vote="+"/>
<voter id="300003" vote="+"/>
<voter id="400546" vote="-"/>
...
</roll>
Имена сенаторов не включены в файл, так что в первую очередь нужно выяснить идентификаторы Фриста и Керри. Затем просмотреть все XML-файлы законопроектов, открыть соответствующие файлы голосований и, наконец, использовать выражение XPath (или даже XQuery), чтобы проверить, отличаются ли голоса.
А что если кому-нибудь захочется узнать, коррелируют ли голоса с возрастом представителей, размером вложений в кампанию, географическим положением его или её округа? Или, ещё лучше, как насчёт вопроса о том, делал ли совет директоров компании Disney пожертвования представителям, предложившим законодательство о копирайте? На сайте GovTrack есть эта информация (она доступна с серверов бюро переписи, федеральной избирательной комиссии, комиссии по ценным бумагам и биржам). Если мы можем с лёгкостью задавать такие вопросы, работа становится намного интересней.
Вот хороший вопрос, на который сегодня я могу ответить с помощью простого запроса: какова численность населения округа каждого сенатора? Так выглядит запрос:
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX pol: <tag:govshare.info,2005:rdf/politico/>
PREFIX census: <tag:govshare.info,2005:rdf/census/>
SELECT ?name ?statename ?population WHERE {
?person foaf:name ?name .
?person pol:hasRole
[ pol:forOffice [ pol:represents ?state ] ] .
?state dc:title ?statename .
?state census:population ?population . }
Это запрос SPARQL, возвращающий таблицу имён сенаторов, названий соответствующих штатов и численность их населения. SPARQL — это новый язык запросов к информации в формате RDF. Я действительно рекомендую прочитать моё собственное «Введение в RDF», и не из пустого желания похвастаться. Я описываю RDF не как простой формат метаданных XML, а иду намного дальше, хотя сегодня RDF понимается именно как универсальный формат обмена данными. В качестве источника информации по самому SPARQL я рекомендую учебник Лейа Додда на XML.com, «Введение в SPARQL: запросы в семантическом вебе».
Вы можете поиграться с запросами к данным на GovTrack здесь, но в этой статье мне не хочется говорить о SPARQL. Я просто хотел показать, что виды вопросов, которые можно задавать становятся намного интереснее и сложнее, если использовать RDF. Никакой запрос XPath или XQuery не сможет быть столь же лаконичен.
Конечно, то же самое можно сделать и с помощью XML, а не RDF и различие лишь в том, на каком этапе объединения данных придётся приложить наибольшее количество сил. В случае XML нагрузка ложится на человека, составляющего запрос. Ему необходимо разобраться в том, какие элементы и атрибуты находятся в каждом XML-файле и как они связаны с другими файлами. Для объединения данных нужно писать специальный склеивающий код. При использовании RDF, нагрузка лежит на людях, обладающих данными. Им нужно удостовериться в перекрытии их идентификаторами других источников данных. Сложности здесь, в основном, в разработке структуры данных, что, конечно, тоже трудно. Но преимущество заключается в том, что разрозненные данные объединяются один раз, людьми, хорошо знающими данные, а не много раз каждым программистом, которому нужна информация.
В оставшейся части статьи я опишу некоторые особенности структуры RDF данных сайта GovTrack. (Вы можете скачать и поработать с RDF.)
Вот некоторые биографические данные о сенаторе Шумере из Нью-Йорка:
@prefix rdf:
<http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix pol: <tag:govshare.info,2005:rdf/politico/> .
@prefix usgov: <tag:govshare.info,2005:rdf/usgovt/> .
@prefix people:
<tag:govshare.info,2005:data/us/congress/people/> .
people:S000148
rdf:type pol:Politician ;
foaf:name "Charles Schumer" ;
foaf:gender "male" ;
usgov:party "Democrat" .
Это данные RDF в формате, называемом
Нотация 3,
отличной альтернативе XML-формату RDF. Так как RDF, в
действительности, — абстрактный способ представления данных, мы
вольны каждый раз выбирать наиболее удобный для чтения (ввода,
обмена) конкретный формат, в соответствии с задачей и данными.
(если вы сомневаетесь, используйте
тест, чтобы
отобразить соответствующие связи). В этих данных подразумевается,
что объект, обозначаемый URI
tag:govshare.info,2005:data/us/congress/people/s000148
(получен простым склеиванием строк префикса URI и локального имени) —
политик, у него есть имя, он демократ и т. д.
Кроме представленных выше данных, есть сведения о роли Шумера в Конгрессе, включая штат, который он представляет. Вот где нужно принимать решение по моделированию структуры данных. Есть несколько разумных путей соотнесения политика и региона, который он или она представляет. Например такой:
people:S00148 pol:represents "New York" .
Это очень по существу. Шумер представляет Нью-Йорк. Это верно,
но не вполне точно. Само выражение «Нью-Йорк» может ввести в
заблуждение: штат Нью-Йорк или город Нью-Йорк? Проблему можно было
бы решить, указав в словаре
pol:, что
pol:represents указывает исключительно на штаты, а не
на города, что выполняло бы задачу, если бы такое ограничение было
допустимо. Но можно сделать небольшое изменение для улучшения
ситуации:
@prefix states: <tag:govshare.info,2005:data/us/> .
people:S00148 pol:represents states:ny .
Теперь всё точно. Кроме того, что компьютер не поймёт смысл URI
tag:govshare.info,2005:data/us/ny. Так что где-то ещё
придётся указать:
@prefix dc: <http://purl.org/dc/elements/1.1/> .
states:ny rdf:type <tag:govshare.info,2005:rdf/usgovt/State> .
states:ny dc:isPartOf <tag:govshare.info,2005:data/us> .
(i.e. the United States)
Компьютер может не понимать, что означает
tag:govshare.info,2005:rdf/usgovt/State, но хотя бы
будет знать, что этот объект относится к тому же типу, что и другие
штаты. Или же автор приложения может присвоить определённое
значение URI
tag:govshare.info,2005:rdf/usgovt/State.
Использование URI вместо конкретного значения позволяет дополнять информацию об объекте. Если я публикую информацию о Конгрессе, а кто-то другой преобразует данные переписи в следующий вид:
@prefix census: <tag:govshare.info,2005:rdf/census/> .
states:ny census:population "18976457" .
то сразу же можно будет выполнять запросы, объединяющие оба массива данных.
Это хороший способ представления информации. После этой черты
всякий выбор в составлении модели данных является компромиссом
между простотой и информативностью. В указанном выше представлении
pol:represents есть два недостатка. Первый заключается
в отсутствии обобщения: каждый сенатор из Нью-Йорка представляет
Нью-Йорк. Лучше сказать, что представление Нью-Йорка не
неотъемлемое свойство Шумера, а следствие другого его свойства — он
занимает пост сенатора от Нью-Йорка. Тогда нужно видоизменить
данные так:
@prefix senate:
<tag:govshare.info,2005:data/us/congress/senate/> .
people:S00148 pol:holdsOffice senate:ny .
senate:ny pol:represents states:ny .
Это решение более информативно ценой большей сложности написания и запросов.
Второй недостаток — следствие свойств реального мира и заключается в том, что наша модель, в отличие от реальности, статична. На это можно посмотреть с двух сторон. Во-первых, то, что Шумер занимает место сенатора, не является его неотъемлемым свойством. Сравните это с приведённым выше предположением, что Нью-Йорк является частью Соединённых Штатов, что мы можем обосновано назвать постоянно истинным. С другой стороны, это верно сейчас, но изменится, когда Шумер уйдёт со своего поста. И так, когда мы пишем RDF, мы фиксируем независимую от времени информацию или верную лишь на момент написания?
Ответ заключается в том, что мы не знаем. Некоторые утверждения изменяются со временем, а некоторые нет. Большое количество RDF в интернете содержат изменяющуюся со временем информацию, без указания на дату написания или срок, в течение которого эта информация верна. Эту проблему предстоит разрешить в будущем.
Хотя можно было бы оставить структуру данных статичной, GovTrack идёт на шаг впереди и моделирует время пребывания сенатора на должности:
@prefix time:
<http://pervasive.semanticweb.org/ont/2004/06/time#> .
people:S00148 pol:hasRole
[
rdf:type pol:Term ;
time:from [ time:at "2005-01-01" ] ;
time:to [ time:at "2010-12-31" ] ;
pol:forOffice senate:ny .
] .
На практике это даёт то преимущество, что GovTrack предоставляет исторические данные и при этом не кажется, будто Джордж Вашингтон всё ещё занимает свою должность.
В семантическом вебе легко застрять в теории. Вопросы моделирования очень интересно обдумывать (по крайней мере, мне), но всё же хорошо иметь и практические приложения, хотя бы время от времени. Следите за обновлениями сайта. В своей следующей статье я опишу основы встраивания правительственных данных в семантический веб.
На последок небольшое замечание. Так как я американец, то знаю достаточно много о собственном правительстве и мало о правительствах других стран. Было бы интересно видеть ваши комментарии о семантическом вебе и правительствах других стран.