<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>шаманские бредни</title>
	<atom:link href="http://shamansir.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://shamansir.wordpress.com</link>
	<description>исследования окружающего мира, основанные на нестандартном подходе</description>
	<lastBuildDate>Sat, 21 Jan 2012 09:26:19 +0000</lastBuildDate>
	<language>ru</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='shamansir.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>шаманские бредни</title>
		<link>http://shamansir.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://shamansir.wordpress.com/osd.xml" title="шаманские бредни" />
	<atom:link rel='hub' href='http://shamansir.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Переезд</title>
		<link>http://shamansir.wordpress.com/2011/01/04/%d0%bf%d0%b5%d1%80%d0%b5%d0%b5%d0%b7%d0%b4/</link>
		<comments>http://shamansir.wordpress.com/2011/01/04/%d0%bf%d0%b5%d1%80%d0%b5%d0%b5%d0%b7%d0%b4/#comments</comments>
		<pubDate>Mon, 03 Jan 2011 20:13:28 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/?p=112</guid>
		<description><![CDATA[Опять переезжаю. Здесь русская версия блога. (кстати, там уже статей на четыре-пять больше, чем здесь) Здесь английская версия (избранные переведённые русские статьи) блога. Это последний переезд до того, как я наконец соберусь купить/оформить себе полноценный хостинг. То есть, ничего не гарантирую :).<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=112&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Опять переезжаю.</p>
<p><a href="http://shamansir-ru.tumblr.com">Здесь</a> русская версия блога. (кстати, там уже статей на четыре-пять больше, чем здесь)<br />
<a href="http://shamansir.tumblr.com">Здесь</a> английская версия (избранные переведённые русские статьи) блога.</p>
<p>Это последний переезд до того, как я наконец соберусь купить/оформить себе полноценный хостинг. То есть, ничего не гарантирую :).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/112/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=112&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2011/01/04/%d0%bf%d0%b5%d1%80%d0%b5%d0%b5%d0%b7%d0%b4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>
	</item>
		<item>
		<title>Подготовка учебных и научных документов в LaTeX</title>
		<link>http://shamansir.wordpress.com/2010/02/21/latex-study-docs/</link>
		<comments>http://shamansir.wordpress.com/2010/02/21/latex-study-docs/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 15:26:52 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[open-source]]></category>
		<category><![CDATA[tex / latex]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[gnumeric]]></category>
		<category><![CDATA[inkscape]]></category>
		<category><![CDATA[latex]]></category>
		<category><![CDATA[tex]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/?p=101</guid>
		<description><![CDATA[В этой статье я вкратце расскажу об общих способах при подготовке различных учебных документов в LaTeX, а конкретно &#8211; о подготовке титульной страницы, вставке векторных рисунков (схем), вставке таблиц и вставке графиков, создающихся на основе подготовленных данных, занесённых или даже вычисляемых в электронной таблице. Процесс будет рассматриваться со стороны Ubuntu/TeX Live, хотя всё рассказанное можно [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=101&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a title="This acrticle at wikidot.com" href="http://shaman-sir.wikidot.com/latex-study-works"><img style="float:right;border:none;" src="http://shamansir.files.wordpress.com/2008/05/wikidot.gif?w=16&#038;h=16" alt="This acrticle at wikidot.com" width="16" height="16" /></a></p>
<p>В этой статье я вкратце расскажу об общих способах при подготовке различных учебных документов в LaTeX, а конкретно &#8211; о подготовке титульной страницы, вставке векторных рисунков (схем), вставке таблиц и вставке графиков, создающихся на основе подготовленных данных, занесённых или даже вычисляемых в электронной таблице.</p>
<p>Процесс будет рассматриваться со стороны Ubuntu/TeX Live, хотя всё рассказанное можно будет сделать и в Windows с использованием MikTeX и на Маке с использованием MacTeX. Также я затрону дополнительные open-source пакеты (версии которых, опять же, есть для всех операционных систем), которые помогут в процессе и опишу какие действия необходимо предпринять, чтобы получившийся в результате документ выглядел максимально близко к желаемому :). Это <a href="http://www.inkscape.org">Inkscape</a>, <a href="http://www.gnome.org/gnumeric">Gnumeric</a> и пакеты <code><a href="http://pgfplots.sourceforge.net">pgfplots</a></code> и <code><a href="http://pgfplots.sourceforge.net">pgfplotstable</a></code> для LaTex.<br />
<span id="more-101"></span><br />
Если вы в первый раз используете LaTeX, рекомендую стандартный <a href="http://www.rpi.edu/dept/arc/docs/latex/latex-intro.pdf">вводный документ</a> <sub>(англ., PDF)</sub> и небольшой <a href="http://en.wikibooks.org/wiki/LaTeX/Formatting">справочник по форматированию текста</a> <sub>(англ.)</sub>.<br />
В качестве документации к <code>pgfplots</code> подойдёт официальная: <a href="http://pgfplots.sourceforge.net/pgfplots.pdf">pgplots</a> <sub>(англ., PDF)</sub> , <a href="http://pgfplots.sourceforge.net/pgfplotstable.pdf">pgplotstable</a> <sub>(англ., PDF)</sub>.</p>
<h2>Установка</h2>
<p>Устанавливаем LaTeX:</p>
<p><code>$ sudo apt-get install tex-common texlive-base texlive-base-bin texlive-common texlive-doc-base texlive-fonts-recommended texlive-lang-cyrillic texlive-latex-base texlive-latex-recommended</code></p>
<p>Создадим тестовый документ в любом редакторе (для <code>gedit</code> вы можете установить <code>gedit-latex-plugin</code>). Условимся, что наш основной документ будет называться <code>work_0001_2010.tex</code>, а все относящиеся к нему файлы будут использовать это название + какой-либо постфикс:</p>
<p><code>$ touch ./work_0001_2010.tex<br />
$ gedit ./work_0001_2010.tex</code></p>
<p>Вставим представленный текст в качестве содержимого, сохраним:</p>
<p><code>\documentclass[a4paper,12pt]{article}<br />
\usepackage[T2A]{fontenc}<br />
\usepackage[utf8]{inputenc} % любая желаемая кодировка<br />
\usepackage[russian,english]{babel}<br />
\usepackage[pdftex,unicode]{hyperref}<br />
\usepackage{indentfirst} % включить отступ у первого абзаца</p>
<p>\title{Заголовок документа}<br />
\author{Имя автора}<br />
\date{02/2010}</p>
<p>\begin{document} % начало документа</p>
<p>\maketitle % заголовок</p>
<p>Тестовый документ, подготовленный в \LaTeX<br />
\end{document} % конец документа</code></p>
<p>Скомпилируем и посмотрим, что получилось:</p>
<p><code>$ pdflatex ./work_0001_2010.tex<br />
$ evince ./work_0001_2010.pdf</code></p>
<p>Если всё было сделано правильно &#8211; перед нами готовый результат.</p>
<h2>Титульная страница</h2>
<p>Итак, генерируемая по умолчанию страница обычно не соответствует тому, что ожидают преподаватели или ученики. Я просто покажу шаблон и то, что должно из него получиться &#8211; результат больше похож на ожидания, но конечно, при желании или необходимости, вы можете изменить его как заблагорассудится.</p>
<p><code>\begin{document} % начало документа</p>
<p>\begin{titlepage} % начало титульной страницы</p>
<p>\begin{center} % включить выравнивание по центру</p>
<p>\large Российский технический институт &lt;&gt;\\[4.5cm]<br />
% название института, затем отступ 4,5см</p>
<p>\huge Теоретическая работа \No 5\\[0.6cm] % название работы, затем отступ 0,6см<br />
\large по~теме &lt;&gt;\\[3.7cm]<br />
% тема работы, затем отступ 3,7см</p>
<p>\begin{minipage}{0.5\textwidth} % начало маленькой врезки в половину ширины текста<br />
\begin{flushleft} % выровнять её содержимое по левому краю<br />
\emph{Автор:} Цокотуха~Флай\\<br />
\emph{Группа:} 7822\\<br />
\emph{Факультет:} МХХПХХ\\<br />
\emph{Преподаватель:} Шаманова~Эллина~Канделябровна<br />
\end{flushleft} % конец выравнивания по левому краю<br />
\end{minipage} % конец врезки</p>
<p>\vfill % заполнить всё доступное ниже пространство</p>
<p>{\large \today} % вывести дату<br />
{\large \LaTeX} % вывести логотип LaTeX</p>
<p>\end{center} % закончить выравнивание по центру</p>
<p>\thispagestyle{empty} % не нумеровать страницу<br />
\end{titlepage} % конец титульной страницы</p>
<p>\tableofcontents % содержание</p>
<p>\section{Глава I}<br />
\section{Глава II}<br />
\section{Глава III}<br />
\section{Глава IV}</p>
<p>Тестовый документ, подготовленный в \LaTeX<br />
\end{document} % конец документа</code></p>
<p>Содержание включено для примера и оно обновится в соотвествии с главами только при следующей компиляции &#8211; это правило для LaTeX. В результате всё это должно выглядеть так:</p>
<p><img src="http://shaman-sir.wikidot.com/local--files/latex-study-works/latex_habr_titlepage.png" style="border:1px solid #000;" /></p>
<h2>Схемы</h2>
<p>Есть много способов вставить изображение в LaTeX-документ, и вам подойдёт любой из них, но так как я обо всём рассказываю, то должен рассказать хотя бы об одном. Я подготавливаю схемы в <a href="http://www.inkscape.org">Inkscape</a> (свободный векторный редактор), экспортирую их в PDF и затем вставляю в LaTeX-документ.</p>
<p>Inkscape очень удобен для подготовки схем &#8211; у прямых линий (да и у фигур и кривых) можно установить с любых концов стрелки или сделать их пунктирными (Object &rarr; Fill and Stroke &rarr; Stroke Style), сектора можно делать ограничивая углы развёртки у круга, любую фигуру можно залить стандартными для таких схем кистями (хоть в полька-точечку (Object &rarr;  Fill and Stroke &rarr;  Fill Style &rarr; Polka dots)), кривые удобно рисовать инструментом Кривая Безье и кроме всего прочего есть &laquo;примагничивание&raquo; (правда оно почему-то включается в свойствах документа (File &rarr;  Document Properties &rarr;  Snap)). Практически любой график или схему из методички/учебника можно перенести в векторный вид за полчаса.</p>
<p>Итак, экспорт из Inkscape. Исходный файл, по принятому ранее соглашению, назовём <code>work_0001_2010_graph01.svg</code></p>
<p>В меню File &rarr; Save as&#8230; выберем формат <code>*.pdf</code>:</p>
<p><img /></p>
<p>И отметим конвертацию шрифтов в пути (в Stroke Style &rarr; Width у надписей советую ставить значения <code>0.1</code>-<code>0.3</code>, иначе надписи в pdf-файле получаются очень толстыми):</p>
<p><img /></p>
<p>Теперь в шапку LaTeX-документа наряду с остальными пакетами нужно добавить пакет <code>graphicx</code>:</p>
<p><code>\usepackage{graphicx}</code></p>
<p>А в тело документа вставить новую картинку:</p>
<p><code>\newpage</p>
<p>Картинка:</p>
<p>\begin{figure}<br />
\centering<br />
\includegraphics[width=0.9\textwidth]{work_0001_2010_graph01.pdf}<br />
\caption{Преломление света}<br />
\label{fig:graph01}<br />
\end{figure}</code></p>
<p>Заново компилируем:</p>
<p><code>$ pdflatex ./work_0001_2010.tex<br />
$ evince ./work_0001_2010.pdf</code></p>
<p>И вот результат:</p>
<p><img /></p>
<h2>Пакеты pgf</h2>
<p>Пакет <code>pgfplotstable</code> помогает  очень гибко настраивать/составлять таблицы и позволяет считывать таблицу из csv-файла при компиляции.</p>
<p>Пакет <code>pgfplots</code> позволяет строить практически любые цветные настраиваемые графики на основе таблиц.</p>
<p>Установка пакетов на Windows/MikTex описана в <a href="http://pgfplots.sourceforge.net/pgfplots.pdf">документации</a> <sub>(англ., PDF)</sub> , в случае Ubuntu нужно сделать следующее:</p>
<p><code>$ sudo nano /etc/apt/sources.list</code></p>
<p>В конец файла добавить (заменять версию <code>lucid</code> на вашу не нужно):</p>
<p><code>deb http://ppa.launchpad.net/johannes-reinhardt/ppa/ubuntu lucid main</code></p>
<p>Выполнить:</p>
<p><code>$sudo apt-get update<br />
$sudo apt-get install pgfplots</code></p>
<h3>Таблицы</h3>
<p>Таблицы будем подготавливать в <a href="http://www.gnome.org/gnumeric">Gnumeric</a>. Можно использовать любой табличный редактор, главное &#8211; гибкая возможность экспорта в текстовый вид. </p>
<p>Создадим таблицу, в первых трёх столбцах которой будут различные значения, а в четвёртом столбце &#8211; среднее по этим трём значениям и сохраним её под именем <code>work_0001_2010_table01.gnumeric</code> (кстати, gnumeric умеет сохранять таблицы в формате LaTeX, но мы намереваемся использовать пакет <code>pgfplotstable</code>, поэтому не будем этого делать):</p>
<p><img /></p>
<p>Теперь необходимо экспортировать таблицу в текстовый файл. Важно заметить две вещи, первая: в текстовый файл импортируется только текущий лист (Sheet), вторая: для того, чтобы удобно работать со столбцами при использовании пакета <code>pgfplotstable</code>, необходимо в первой строке таблицы указать короткие однословные названия (алиасы) для столбцов.</p>
<p>Таблицу можно сохранить в CSV, но если вы используете русскую локаль в операционной системе, то дробные числа в таблице будут представлены с использованием запятой. Так что лучше сохраним файл в формате Text (configurable), а назовём его, для удобства, <code>work_0001_2010_table01.dat</code></p>
<p><img /></p>
<p>После этого вас спросят о дополнительных настройках &#8211; символ конца строки установите в соответствии с вашей операционной системой, разделитель &#8211; &laquo;пробел&raquo; и отключите кавычки.</p>
<p><img /></p>
<p>В результате должен получиться такой файл:</p>
<p><code>a b c mid<br />
0.09 0.07 0.072 0.0773333333333333<br />
0.15 0.073 0.073 0.0986666666666667<br />
0.155 0.074 0.8 0.343<br />
0.156 0.078 0.9 0.378<br />
0.17 0.079 0.99 0.413<br />
0.18 0.08 0.1 0.12<br />
0.189 0.09 0.12 0.133<br />
0.192 0.1 0.14 0.144<br />
0.195 0.12 0.153 0.156<br />
0.2 0.128 0.16 0.162666666666667</code></p>
<p>Теперь можно вставить таблицу в LaTeX-документ. Добавьте в заголовок:</p>
<p><code>\usepackage{pgfplotstable}</code></p>
<p>Теперь, в теле документа, настроим вывод у пакета pgf (запятые в качестве дробных разделитей, разделитель в файлах данных по умолчанию пробел, округление до шести знаков) и загрузим файл с данными, привязав его к алиасу <code>midvalues</code>:</p>
<p><code>\pgfkeys{/pgf/number format/.cd,precision=6,use comma,fixed,1000 sep={}}</p>
<p>\pgfplotstableread{work_0001_2010_table01.dat}\midvalues</code></p>
<p>Теперь опишем саму таблицу:</p>
<p><code>\newpage</p>
<p>Таблица</p>
<p>\begin{table}[h]<br />
\centering<br />
\caption{Средние числа}<br />
\pgfplotstabletypeset[<br />
&nbsp;&nbsp;&nbsp;&nbsp;columns={a,b,c,mid},  % алиасы колонок, определённые в первой строке таблицы<br />
&nbsp;&nbsp;&nbsp;&nbsp;columns/a/.style={ column name=Значение $a$ }, % стиль столбца: определяем только заголовок<br />
&nbsp;&nbsp;&nbsp;&nbsp;columns/b/.style={ column name=Значение $b$ }, % стиль столбца: определяем только заголовок<br />
&nbsp;&nbsp;&nbsp;&nbsp;columns/c/.style={ column name=Значение $c$ }, % стиль столбца: определяем только заголовок<br />
&nbsp;&nbsp;&nbsp;&nbsp;columns/mid/.style={ column name=Среднее значение }, % стиль столбца: определяем только заголовок<br />
&nbsp;&nbsp;&nbsp;&nbsp;every head row/.style={ before row=\hline, after row=\hline\hline }, % одиночная линия над и двойная линия под первой строкой таблицы<br />
&nbsp;&nbsp;&nbsp;&nbsp;every last row/.style={ after row=\hline }, % одиночная линия под последней строкой таблицы<br />
&nbsp;&nbsp;&nbsp;&nbsp;every first column/.style={<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;column type/.add={|}{} % вертикальная линия перед первым столбцом<br />
&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;every last column/.style={<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;column type/.add={|}{|} % вертикальные линии с обоих сторон последнего столбца<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
]\midvalues \\[0.5cm]<br />
\label{tab:midvalues}<br />
\end{table}</code></p>
<p>Снова перекомпилируем файл, и вот результат:</p>
<p><img /></p>
<h3>Графики</h3>
<p>В завершение построим график по данной таблице. </p>
<p>Добавьте в заголовок документа:</p>
<p><code>\usepackage{pgfplots}<br />
\pgfplotsset{compat=newest} % использовать новые возможности pgfplots</code></p>
<p>И, в тело документа:</p>
<p><code>\newpage</p>
<p>\begin{tikzpicture}<br />
&nbsp;&nbsp;&nbsp;&nbsp;\begin{axis}[ % начать график<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xlabel=Измерение, % метка для оси x<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ylabel=Значение, % метка для оси y<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xtick align=center, % риски оси x внутри графика<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yminorgrids, ymajorgrids, % линии для основных и второстепенных значений по оси y<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xmajorgrids, % линии для основных значений по оси x<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;minor y tick num=4, % 4 второстепенных риски между каждыми основными рисками по оси y<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;legend style={at={(0.74,0.74)}, anchor=south west} % позиционирование легенды относительно нижнего левого угла<br />
&nbsp;&nbsp;&nbsp;&nbsp;],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\addplot[green!40!black,mark=x] table[y=a] from \midvalues; % тёмно-зелёным отметить данные из столбца 'a' на оси таблицы midvalues<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\addlegendentry{$a$ (таб. \ref{tab:midvalues})} % добавить линию на легенду<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\addplot[red!60!black,mark=x] table[y=b] from \midvalues; % тёмно-красным отметить на оси y данные из столбца 'b' таблицы midvalues<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\addlegendentry{$b$ (таб. \ref{tab:midvalues})} % добавить линию на легенду<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\addplot[yellow!80!black,mark=x] table[y=c] from \midvalues; % тёмно-жёлтым отметить на оси y данные из столбца 'c' таблицы midvalues<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\addlegendentry{$c$ (таб. \ref{tab:midvalues})} % добавить линию на легенду<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\addplot[blue!80!black,mark=o,smooth] table[y=mid] from \midvalues; % тёмно-синей сглаженной линией отметить на оси y данные из столбца 'mid' таблицы midvalues<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\addlegendentry{Среднее (таб. \ref{tab:midvalues})}  % добавить линию на легенду<br />
&nbsp;&nbsp;&nbsp;&nbsp;\end{axis}<br />
\end{tikzpicture}</code></p>
<p>Мы указываем только значения для оси y и pgf автоматически подбирает значения на оси x, но в команде <code>addplot</code> также можно указать и столбец-источник для оси x: <code>table[x=mid,y=b]</code> </p>
<p>Снова перекомпиляция, и теперь мы видим отличный график-за-пять-минут по нашим значениям (значения я подбирал наугад, поэтому выглядят они не очень удачно (чуть лучше на графике с логарифмическими осями, однако задание сделать его таковым я лучше оставлю вам на дом), но надеюсь суть понятна).</p>
<p><img /></p>
<p>Я привёл лишь простейший пример, но пакет <code>pgfplots</code> обладает настолько широкими возможностями, что если вы заинтересованы в данной теме, то вы просто обязаны хотя бы очень подробно рассмотреть всё <a href="http://pgfplots.sourceforge.net/pgfplots.pdf">руководство по пакету</a> <sub>(англ., PDF)</sub>.</p>
<h2>Заключение</h2>
<p>Итак, LaTeX и <code>pgfplots</code> &#8211; удобный способ оформлять не только текстовые документы с формулами, но и целые работы со схемами, графиками и таблицами. Причём делать их просто и удобно. Желаю вам большого количества полезных и легко созданных научных работ!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/101/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=101&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2010/02/21/latex-study-docs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/05/wikidot.gif" medium="image">
			<media:title type="html">This acrticle at wikidot.com</media:title>
		</media:content>

		<media:content url="http://shaman-sir.wikidot.com/local--files/latex-study-works/latex_habr_titlepage.png" medium="image" />
	</item>
		<item>
		<title>На клиенте! Получить XML! Получить XSL! Сделать XHTML! Марш!</title>
		<link>http://shamansir.wordpress.com/2009/02/04/get-xml-get-xsl-do-xhtm/</link>
		<comments>http://shamansir.wordpress.com/2009/02/04/get-xml-get-xsl-do-xhtm/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 07:51:26 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[девелопмент]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[стандарты и технологии]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[xsd]]></category>
		<category><![CDATA[xsl]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/?p=96</guid>
		<description><![CDATA[X-Task: &#171;On your Client! Get XML! Get XSL! Do XHTML! Go!&#187; Вступление Статья рассматривает преобразование XML в XHTML посредством XSLT на клиенте средствами JavaScript. К примеру, у вас есть какие-либо данные в виде XML, а вам требуется по какому-либо действию клиента (по клику на ссылке), оформить их в [X]HTML и динамически вставить в страницу. Это [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=96&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a title="This acrticle at wikidot.com" href="http://shaman-sir.wikidot.com/client-xml-xslt-xhtml-browsers"><img style="float:right;border:none;" src="http://shamansir.files.wordpress.com/2008/05/wikidot.gif?w=16&#038;h=16" alt="This acrticle at wikidot.com" width="16" height="16" /></a></p>
<p><a title="JavaScript" href="http://www.ecma-international.org/publications/standards/Ecma-262.htm"><img style="border:1px dotted #000000;" src="http://shamansir.files.wordpress.com/2007/08/javascript.png?w=575" alt="JavaScript" /></a></p>
<p><strong>X-Task: &laquo;On your Client! Get XML! Get XSL! Do XHTML! Go!&raquo;</strong></p>
<h2>Вступление</h2>
<p>Статья рассматривает преобразование XML в XHTML посредством XSLT на клиенте средствами JavaScript. К примеру, у вас есть какие-либо данные в виде XML, а вам требуется по какому-либо действию клиента (по клику на ссылке), оформить их в [X]HTML и динамически вставить в страницу. Это не так сложно, но по пути, как оказалось, встречается несколько подводных камней — в основном, относительно кросс-браузерности этого подхода и малой освещённости процесса в сети. <em>Генерация XHTML-страниц средствами браузера (прямой запрос на XML файл, содержащий информацию о стиле) — это другая тема, она намного проще, и здесь затронута не будет.</em></p>
<p>Задача будет рассмотрена на банальном примере личного сайта. Дано: Файл с контактными данными (XML), некая главная страница (XHTML) и пять браузеров: Firefox 3, Opera 9.5, IE7, Safari 3, Google Chrome. На главной странице есть ссылка, при нажатии которой контактные данные преобразуются в несортированный список (<tt>UL</tt>) и отображаются в специально выделенной области прямо на этой странице. Это реальный рабочий пример, который я сейчас использую для создания своего сайта (ещё не выложенного).</p>
<p><span id="more-96"></span></p>
<h2>XML</h2>
<p>Контактные данные, при их большом количестве, можно сгруппировать, поэтому XML-схема построена с учётом группировки элементов. Группа имеет краткое имя (<tt>shortname</tt>) для создания <tt>id</tt> у списка (возможно, потребуется оформить каждую группу по-особому) и, собственно, имя группы. XML-файл может содержать <tt>contact</tt>-ноды и вне групп, но в данном примере в этом нет необходимости. Все контакты имеют тип (<tt>type</tt>) для создания корректных ссылок в будущем (это мы также опустим). С остальным, вроде бы, всё понятно:</p>
<p><img src="http://shaman-sir.wikidot.com/local--files/client-xml-xslt-xhtml-browsers/xml-schema-example.jpg" alt="XML Schema" width="450" height="500" /></p>
<p>Структура довольно-таки проста, поэтому приведу сразу пример файла (любое сходство с реальными данными какого-либо индивидуума полностью случайно и приведено не намеренно):</p>
<blockquote>
<ol>
<li><span style="color:#009900;"><span style="color:#000000;">&lt;?xml</span> <span style="color:#000066;">version</span>=<span style="color:#ff0000;">&laquo;1.0&#8243;</span> <span style="color:#000066;">encoding</span>=<span style="color:#ff0000;">&laquo;UTF-8&#8243;</span><span style="color:#000000;">?&gt;</span></span></li>
<li><span style="color:#009900;"><span style="color:#000000;">&lt;?xml-stylesheet</span> <span style="color:#000066;">type</span>=<span style="color:#ff0000;">&laquo;text/xsl&raquo;</span> <span style="color:#000066;">href</span>=<span style="color:#ff0000;">&laquo;./contacts.xsl&raquo;</span><span style="color:#000000;">?&gt;</span></span></li>
<li><span style="color:#009900;"><span style="color:#000000;">&lt;contacts</span> </span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">xmlns</span>=<span style="color:#ff0000;">&laquo;http://any-developer.name&raquo;</span> </span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">xmlns:xsi</span>=<span style="color:#ff0000;">&laquo;http://www.w3.org/2001/XMLSchema-instance&raquo;</span> </span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">xsi:schemaLocation</span>=<span style="color:#ff0000;">&laquo;http://any-developer.name ./contacts.xsd&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;group</span> <span style="color:#000066;">shortname</span>=<span style="color:#ff0000;">&laquo;messengers&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;name<span style="color:#000000;">&gt;</span></span></span>Messengers<span style="color:#009900;"><span style="color:#000000;">&lt;/name<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;contact</span> <span style="color:#000066;">type</span>=<span style="color:#ff0000;">&laquo;skype&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;id<span style="color:#000000;">&gt;</span></span></span>any.developer<span style="color:#009900;"><span style="color:#000000;">&lt;/id<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/contact<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;contact</span> <span style="color:#000066;">type</span>=<span style="color:#ff0000;">&laquo;jabber&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;id<span style="color:#000000;">&gt;</span></span></span>any.developer@jabber.org<span style="color:#009900;"><span style="color:#000000;">&lt;/id<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;name<span style="color:#000000;">&gt;</span></span></span>ulric.wilfred<span style="color:#009900;"><span style="color:#000000;">&lt;/name<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/contact<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;contact</span> <span style="color:#000066;">type</span>=<span style="color:#ff0000;">&laquo;gtalk&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;id<span style="color:#000000;">&gt;</span></span></span>any.developer<span style="color:#009900;"><span style="color:#000000;">&lt;/id<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/contact<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;contact</span> <span style="color:#000066;">type</span>=<span style="color:#ff0000;">&laquo;yahoo&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;id<span style="color:#000000;">&gt;</span></span></span>any.developer<span style="color:#009900;"><span style="color:#000000;">&lt;/id<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/contact<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;contact</span> <span style="color:#000066;">type</span>=<span style="color:#ff0000;">&laquo;icq&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;id<span style="color:#000000;">&gt;</span></span></span>7484939304033345544<span style="color:#009900;"><span style="color:#000000;">&lt;/id<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;name<span style="color:#000000;">&gt;</span></span></span>any.developer<span style="color:#009900;"><span style="color:#000000;">&lt;/name<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/contact<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/group<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;group</span> <span style="color:#000066;">shortname</span>=<span style="color:#ff0000;">&laquo;email&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;name<span style="color:#000000;">&gt;</span></span></span>E-Mail<span style="color:#009900;"><span style="color:#000000;">&lt;/name<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;contact</span> <span style="color:#000066;">type</span>=<span style="color:#ff0000;">&laquo;gmail&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;id<span style="color:#000000;">&gt;</span></span></span>any.developer<span style="color:#009900;"><span style="color:#000000;">&lt;/id<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/contact<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;contact</span> <span style="color:#000066;">type</span>=<span style="color:#ff0000;">&laquo;yahoo-mail&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;id<span style="color:#000000;">&gt;</span></span></span>any.developer<span style="color:#009900;"><span style="color:#000000;">&lt;/id<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/contact<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/group<span style="color:#000000;">&gt;</span></span></span></li>
<li><span style="color:#009900;"><span style="color:#000000;">&lt;/contacts<span style="color:#000000;">&gt;</span></span></span></li>
</ol>
</blockquote>
<h2>XSL</h2>
<p>Стиль генерирует XHTML-код, в виде списка <tt>UL</tt>, состоящего из негруппированных контактов и вложенных списков для групп. Поскольку результат вывода именно <span style="text-decoration:underline;">X</span>HTML, требования к оформлению результата несколько строже, чем если бы это был обычный HTML. Поэтому следует обратить внимание на следующие моменты:</p>
<ul>
<li><strong>Важно:</strong> В результате преобразования должен получаться файл с одной и только одной корневой нодой, иначе Safari и Google Chrome (<em>Читай:</em> WebKit) не смогут добавить результирующий элемент в документ. Это довольно разумно, поскольку для всех XML объектов (результат в виде XHTML из их числа) есть правило: корневой элемент должен быть только один (<em>There can be the only one</em>).</li>
<li><strong>Важно:</strong> В качестве <tt>xsl:output method</tt> должен быть указан либо <tt>xml</tt> либо <tt>html</tt> (однако, в последнем случае, при использовании пронстранств имён, таковые будут потеряны). Некоторые ставят это значение в <tt>xhtml</tt> и в результате получают некорректную обработку или ошибки на клиенте — пока этого метода не введено и не следует его использовать. Для этого есть <tt>media-type</tt>.</li>
<li>Код генерируется без заголовков XML: <tt>omit-xml-declaration</tt> установлен в <tt>yes</tt> и <tt>xmlns</tt> не указывается, иначе в результате получится недоXHTML-файл с XML-заголовком, не содержащий <tt>html</tt>, <tt>head</tt> и <tt>body</tt>. Генерация <tt>DOCTYPE</tt> (<tt>doctype-system</tt>, <tt>doctype-public</tt>) также отключена.</li>
</ul>
<blockquote>
<ol>
<li><span style="color:#009900;"><span style="color:#000000;">&lt;?xml</span> <span style="color:#000066;">version</span>=<span style="color:#ff0000;">&laquo;1.0&#8243;</span> <span style="color:#000066;">encoding</span>=<span style="color:#ff0000;">&laquo;utf-8&#8243;</span><span style="color:#000000;">?&gt;</span></span></li>
<li><span style="color:#009900;"><span style="color:#000000;">&lt;xsl:stylesheet</span> <span style="color:#000066;">version</span>=<span style="color:#ff0000;">&laquo;1.0&#8243;</span></span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">xmlns:xsl</span>=<span style="color:#ff0000;">&laquo;http://www.w3.org/1999/XSL/Transform&raquo;</span></span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">xmlns:c</span>=<span style="color:#ff0000;">&laquo;http://any-developer.name&raquo;</span> <span style="color:#000066;">exclude-result-prefixes</span>=<span style="color:#ff0000;">&laquo;c&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li><span style="color:#808080;">&lt;!&#8211;    xmlns=&raquo;http://www.w3.org/1999/xhtml&raquo; &#8211;&gt;</span></li>
<li></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:output</span> <span style="color:#000066;">method</span>=<span style="color:#ff0000;">&laquo;xml&raquo;</span></span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">encoding</span>=<span style="color:#ff0000;">&laquo;utf-8&#8243;</span></span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">standalone</span>=<span style="color:#ff0000;">&laquo;yes&raquo;</span></span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">indent</span>=<span style="color:#ff0000;">&laquo;yes&raquo;</span></span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">omit-xml-declaration</span>=<span style="color:#ff0000;">&laquo;yes&raquo;</span></span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">media-type</span>=<span style="color:#ff0000;">&laquo;text/xhtml&raquo;</span><span style="color:#000000;">/&gt;</span></span></li>
<li> <span style="color:#808080;">&lt;!&#8211;</span></li>
<li><span style="color:#808080;"> doctype-system=&raquo;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&raquo;</span></li>
<li><span style="color:#808080;"> doctype-public=&raquo;-//W3C//DTD XHTML 1.0 Strict//EN&raquo; </span></li>
<li><span style="color:#808080;"> &#8211;&gt;</span></li>
<li></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:template</span> <span style="color:#000066;">name</span>=<span style="color:#ff0000;">&laquo;contact&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;li<span style="color:#000000;">&gt;</span></span><span style="color:#000000;">&lt;a</span> <span style="color:#000066;">href</span>=<span style="color:#ff0000;">&laquo;javascript:alert(&#8216;{@type}&#8217;)&raquo;</span> <span style="color:#000066;">title</span>=<span style="color:#ff0000;">&laquo;{@type}&raquo;</span> </span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">id</span>=<span style="color:#ff0000;">&laquo;contact-{@type}-sitelink&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;img</span> <span style="color:#000066;">alt</span>=<span style="color:#ff0000;">&laquo;{@type}&raquo;</span> <span style="color:#000066;">src</span>=<span style="color:#ff0000;">&laquo;{@type}.ico&raquo;</span> </span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">id</span>=<span style="color:#ff0000;">&laquo;contact-{@type}-icon&raquo;</span> <span style="color:#000066;">class</span>=<span style="color:#ff0000;">&laquo;contact-icon&raquo;</span> <span style="color:#000000;">/&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/a<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:if</span> <span style="color:#000066;">test</span>=<span style="color:#ff0000;">&laquo;c:name&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;a</span> <span style="color:#000066;">href</span>=<span style="color:#ff0000;">&laquo;javascript:alert(&#8216;{@type}:{c:id}&#8217;);&raquo;</span> </span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">id</span>=<span style="color:#ff0000;">&laquo;contact-{@type}-link&raquo;</span> <span style="color:#000066;">title</span>=<span style="color:#ff0000;">&laquo;{c:id}&raquo;</span> <span style="color:#000066;">alt</span>=<span style="color:#ff0000;">&laquo;{c:name}&raquo;</span></span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">class</span>=<span style="color:#ff0000;">&laquo;contact-link&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:value-of</span> <span style="color:#000066;">select</span>=<span style="color:#ff0000;">&laquo;c:name&raquo;</span><span style="color:#000000;">/&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/a<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/xsl:if<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:if</span> <span style="color:#000066;">test</span>=<span style="color:#ff0000;">&laquo;not(c:name)&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;a</span> <span style="color:#000066;">href</span>=<span style="color:#ff0000;">&laquo;javascript:alert(&#8216;{@type}:{c:id}&#8217;);&raquo;</span> </span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">id</span>=<span style="color:#ff0000;">&laquo;contact-{@type}-link&raquo;</span> <span style="color:#000066;">title</span>=<span style="color:#ff0000;">&laquo;{c:id}&raquo;</span> <span style="color:#000066;">alt</span>=<span style="color:#ff0000;">&laquo;{c:id}&raquo;</span> </span></li>
<li><span style="color:#009900;"> <span style="color:#000066;">class</span>=<span style="color:#ff0000;">&laquo;contact-link&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:value-of</span> <span style="color:#000066;">select</span>=<span style="color:#ff0000;">&laquo;c:id&raquo;</span><span style="color:#000000;">/&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/a<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/xsl:if<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;span</span> <span style="color:#000066;">class</span>=<span style="color:#ff0000;">&laquo;contact-type&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> (<span style="color:#009900;"><span style="color:#000000;">&lt;xsl:value-of</span> <span style="color:#000066;">select</span>=<span style="color:#ff0000;">&laquo;@type&raquo;</span><span style="color:#000000;">/&gt;</span></span>)<span style="color:#009900;"><span style="color:#000000;">&lt;/span<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/li<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/xsl:template<span style="color:#000000;">&gt;</span></span></span></li>
<li></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:template</span> <span style="color:#000066;">match</span>=<span style="color:#ff0000;">&laquo;/c:contacts&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;ul</span> <span style="color:#000066;">id</span>=<span style="color:#ff0000;">&laquo;contacts&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:for-each</span> <span style="color:#000066;">select</span>=<span style="color:#ff0000;">&laquo;./c:contact&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:call-template</span> <span style="color:#000066;">name</span>=<span style="color:#ff0000;">&laquo;contact&raquo;</span> <span style="color:#000000;">/&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/xsl:for-each<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:for-each</span> <span style="color:#000066;">select</span>=<span style="color:#ff0000;">&laquo;./c:group&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;li<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:if</span> <span style="color:#000066;">test</span>=<span style="color:#ff0000;">&laquo;c:name&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;span</span> <span style="color:#000066;">class</span>=<span style="color:#ff0000;">&laquo;contact-group-name&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:value-of</span> <span style="color:#000066;">select</span>=<span style="color:#ff0000;">&laquo;c:name&raquo;</span><span style="color:#000000;">/&gt;</span><span style="color:#000000;">&lt;/span<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/xsl:if<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;ul</span> <span style="color:#000066;">id</span>=<span style="color:#ff0000;">&laquo;{@shortname}&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:for-each</span> <span style="color:#000066;">select</span>=<span style="color:#ff0000;">&laquo;./c:contact&raquo;</span><span style="color:#000000;">&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;xsl:call-template</span> <span style="color:#000066;">name</span>=<span style="color:#ff0000;">&laquo;contact&raquo;</span> <span style="color:#000000;">/&gt;</span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/xsl:for-each<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/ul<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/li<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/xsl:for-each<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/ul<span style="color:#000000;">&gt;</span></span></span></li>
<li> <span style="color:#009900;"><span style="color:#000000;">&lt;/xsl:template<span style="color:#000000;">&gt;</span></span></span></li>
<li></li>
<li><span style="color:#009900;"><span style="color:#000000;">&lt;/xsl:stylesheet<span style="color:#000000;">&gt;</span></span></span></li>
</ol>
</blockquote>
<p>В результате преобразования получается такой блок XHTML:</p>
<p><img src="http://shaman-sir.wikidot.com/local--files/client-xml-xslt-xhtml-browsers/xml-rendering-result.jpg" alt="XML Rendering Result" /></p>
<h2>JavaScript</h2>
<p>Настало время выполнить само преобразование на стороне клиента. В этом абзаце придётся использовать немного больше хитростей, ввиду того, что каждый браузер предлагает это делать по-своему.</p>
<h3>Загрузка XML-файлов</h3>
<p>Для начала нам потребуется загрузить оба файла — XML и XSLT. По своей природе они оба — файлы XML,  Internet Explorer предоставляет для этих целей ActiveX-объект <tt>XMLDOM</tt>, Firefox и Opera — фунцию <tt>createDocument</tt>, позволяющую загрузить XML-файл в созданный объект. Safari и Chrome (<em>Читай:</em> WebKit), однако, предоставляя эту же функцию, возвращают объект, не поддерживающий загрузку — опять же, вполне разумно, в соответствии со спецификациями W3C.</p>
<h4>Метод 1. XMLHttpRequest</h4>
<p>Поэтому, плюнув на всё, мы можем загружать файлы через <tt>XMLHttpRequest</tt> (<em>синхронный</em> или нет — по вашему выбору), используя всем известный шаблон AJAX.</p>
<p>Предложу вам свою версию, вы же можете использовать <a title="Шаблон вызова XMLHttpRequest" href="http://ajaxpatterns.org/XMLHttpRequest_Call">какую только заблагорассудится</a>.  Моя версия отличается тем, что принимает в параметры функцию, которая будет вызвана при успешном завершении вызова, позволяет делать и <tt>POST</tt> и <tt>GET</tt> запросы, позволяет передавать объекты и позволяет делать синхронный вызов (тогда она возвращает объект по его завершению).</p>
<blockquote>
<ol>
<li><span style="color:#006600;">/**</span></li>
<li><span style="color:#006600;"> * Browser-independent [A]JAX call</span></li>
<li><span style="color:#006600;"> * </span></li>
<li><span style="color:#006600;"> * @param {String} locationURL an URL to call, without parameters</span></li>
<li><span style="color:#006600;"> * @param {String} [parameters=null] a parameters list, in the form </span></li>
<li><span style="color:#006600;"> *        &#8217;param1=value1&amp;param2=value2&amp;param3=value3&#8242;</span></li>
<li><span style="color:#006600;"> * @param {Function(XHMLHTTPRequest, Object)} [onComplete=null] a function that</span></li>
<li><span style="color:#006600;"> *        will be called when the response (responseText or responseXML of </span></li>
<li><span style="color:#006600;"> *        XHMLHTTPRequest) will be received</span></li>
<li><span style="color:#006600;"> * @param {Boolean} [doSynchronous=false] make a synchronous request (onComplete</span></li>
<li><span style="color:#006600;"> *        will /not/ be called) </span></li>
<li><span style="color:#006600;"> * @param {Boolean} [doPost=false] make a POST request instead of GET </span></li>
<li><span style="color:#006600;"> * @param {Object} [dataPackage=null] any object to transfer to the onComplete </span></li>
<li><span style="color:#006600;"> *        listener</span></li>
<li><span style="color:#006600;"> * @return {XHMLHTTPRequest} request object, if no exceptions occured</span></li>
<li><span style="color:#006600;"> */</span></li>
<li><span style="color:#003366;">function</span> makeRequest<span style="color:#009900;">(</span>locationURL<span style="color:#339933;">,</span> parameters<span style="color:#339933;">,</span> onComplete<span style="color:#339933;">,</span> doSynchronous<span style="color:#339933;">,</span> doPost<span style="color:#339933;">,</span> dataPackage<span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li></li>
<li> <span style="color:#003366;">var</span> http_request <span style="color:#339933;">=</span> <span style="color:#003366;">false</span>;</li>
<li> <span style="color:#000066;">try</span> <span style="color:#009900;">{</span></li>
<li> http_request <span style="color:#339933;">=</span> <span style="color:#003366;">new</span> ActiveXObject<span style="color:#009900;">(</span><span style="color:#3366cc;">&laquo;Msxml2.XMLHTTP&raquo;</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span> <span style="color:#000066;">catch</span> <span style="color:#009900;">(</span>e1<span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> <span style="color:#000066;">try</span> <span style="color:#009900;">{</span></li>
<li> http_request<span style="color:#339933;">=</span> <span style="color:#003366;">new</span> ActiveXObject<span style="color:#009900;">(</span><span style="color:#3366cc;">&laquo;Microsoft.XMLHTTP&raquo;</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span> <span style="color:#000066;">catch</span> <span style="color:#009900;">(</span>e2<span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> http_request <span style="color:#339933;">=</span> <span style="color:#003366;">new</span> XMLHttpRequest<span style="color:#009900;">(</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span></li>
<li> <span style="color:#009900;">}</span></li>
<li></li>
<li> <span style="color:#006600;">//if (http_request.overrideMimeType) { // optional</span></li>
<li> <span style="color:#006600;">//  http_request.overrideMimeType(&#8216;text/xml&#8217;);</span></li>
<li> <span style="color:#006600;">//}</span></li>
<li></li>
<li> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span><span style="color:#339933;">!</span>http_request<span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> <span style="color:#000066;">alert</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&#8216;Cannot create XMLHTTP instance&#8217;</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#000066;">return</span> <span style="color:#003366;">false</span>;</li>
<li> <span style="color:#009900;">}</span></li>
<li></li>
<li> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span>onComplete <span style="color:#339933;">&amp;&amp;</span> <span style="color:#339933;">!</span>doSynchronous<span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> completeListener <span style="color:#339933;">=</span> <span style="color:#003366;">function</span><span style="color:#009900;">(</span><span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span>http_request.<span style="color:#660066;">readyState</span> <span style="color:#339933;">==</span> <span style="color:#cc0000;">4</span><span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span>http_request.<span style="color:#000066;">status</span> <span style="color:#339933;">==</span> <span style="color:#cc0000;">200</span><span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> onComplete<span style="color:#009900;">(</span>http_request<span style="color:#339933;">,</span> dataPackage<span style="color:#009900;">)</span></li>
<li> <span style="color:#009900;">}</span></li>
<li> <span style="color:#009900;">}</span></li>
<li> <span style="color:#009900;">}</span>;</li>
<li> http_request.<span style="color:#660066;">onreadystatechange</span> <span style="color:#339933;">=</span> completeListener;</li>
<li> <span style="color:#009900;">}</span></li>
<li></li>
<li></li>
<li> <span style="color:#006600;">//var salt = hex_md5(new Date().toString());</span></li>
<li> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span>doPost<span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> http_request.<span style="color:#000066;">open</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&#8216;POST&#8217;</span><span style="color:#339933;">,</span> locationURL<span style="color:#339933;">,</span> <span style="color:#339933;">!</span>doSynchronous<span style="color:#009900;">)</span>;</li>
<li> http_request.<span style="color:#660066;">setRequestHeader</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&laquo;Content-type&raquo;</span><span style="color:#339933;">,</span> <span style="color:#3366cc;">&laquo;application/x-www-form-urlencoded&raquo;</span><span style="color:#009900;">)</span>;</li>
<li> http_request.<span style="color:#660066;">setRequestHeader</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&laquo;Content-length&raquo;</span><span style="color:#339933;">,</span> parameters.<span style="color:#660066;">length</span><span style="color:#009900;">)</span>;</li>
<li> http_request.<span style="color:#660066;">setRequestHeader</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&laquo;Connection&raquo;</span><span style="color:#339933;">,</span> <span style="color:#3366cc;">&laquo;close&raquo;</span><span style="color:#009900;">)</span>;</li>
<li> http_request.<span style="color:#660066;">send</span><span style="color:#009900;">(</span>parameters<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span> <span style="color:#000066;">else</span> <span style="color:#009900;">{</span></li>
<li> http_request.<span style="color:#000066;">open</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&#8216;GET&#8217;</span><span style="color:#339933;">,</span> locationURL <span style="color:#339933;">+</span> <span style="color:#009900;">(</span>parameters <span style="color:#339933;">?</span> <span style="color:#009900;">(</span><span style="color:#3366cc;">&laquo;?&raquo;</span> <span style="color:#339933;">+</span> parameters<span style="color:#009900;">)</span> <span style="color:#339933;">:</span> <span style="color:#3366cc;">&laquo;&raquo;</span><span style="color:#009900;">)</span><span style="color:#339933;">,</span> <span style="color:#339933;">!</span>doSynchronous<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#006600;">//http_request.open(&#8216;GET&#8217;, &#8217;./proxy.php?&#8217; + parameters +</span></li>
<li> <span style="color:#006600;">// &raquo;&amp;salt=&raquo; + salt, true);</span></li>
<li> http_request.<span style="color:#660066;">send</span><span style="color:#009900;">(</span><span style="color:#003366;">null</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span></li>
<li></li>
<li> <span style="color:#000066;">return</span> http_request;</li>
<li></li>
<li><span style="color:#009900;">}</span></li>
</ol>
</blockquote>
<p>При использовании этого метода, функция загрузки XML будет выглядеть довольно просто — например, так:</p>
<blockquote>
<ol>
<li><span style="color:#006600;">/**</span></li>
<li><span style="color:#006600;"> * Loads any XML using synchronous XMLHttpRequest call.</span></li>
<li><span style="color:#006600;"> * @param {String} fileName name of the file to be loaded</span></li>
<li><span style="color:#006600;"> * @return {XMLDocument|Object}</span></li>
<li><span style="color:#006600;"> */</span></li>
<li><span style="color:#003366;">function</span> loadXML<span style="color:#009900;">(</span>fileName<span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> <span style="color:#006600;">// no parameters, no handler, but synchronous</span></li>
<li> <span style="color:#003366;">var</span> request <span style="color:#339933;">=</span> makeRequest<span style="color:#009900;">(</span>fileName<span style="color:#339933;">,</span> <span style="color:#003366;">null</span><span style="color:#339933;">,</span> <span style="color:#003366;">null</span><span style="color:#339933;">,</span> <span style="color:#003366;">true</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#000066;">return</span> request.<span style="color:#660066;">responseXML</span>;</li>
<li><span style="color:#009900;">}</span></li>
</ol>
</blockquote>
<h4>Метод 2. В зависимости от браузера</h4>
<p>Однако, если вы хотите использовать именно те способы, которые (как ни забавно) <a title="W3Schools XSL on the Client" href="http://www.w3schools.com/xsl/xsl_client.asp">рекомендуются</a> на W3Schools, функцию <tt>loadXML</tt> придётся усложнить, потому что приведённые на W3Schoolds примеры не работают на браузерах WebKit (<em>Читай:</em> Safari и Chrome). Пусть это будет, так сказать, <em>«рекомендованный вид»</em>. Подозреваю, правда, что все эти обходы скрывают под собой те же вызовы <tt>XMLHttpRequest</tt>, поэтому, если вы не сторонник неоправданных действий, пропустите этот раздел.</p>
<p>Итак, функция будет делать прямой синхронный вызов <tt>XMLHttpRequest</tt> (вернее, функции описанной в предыдущем разделе) только в случае вызова из Safari, в остальных же случаях прибегать к средствам конкретного браузера (Не забываем правило: <em>Никаких прямых проверок браузера, только проверка, поддерживается ли вызываемая функция</em>):</p>
<blockquote>
<ol>
<li><span style="color:#006600;">/**</span></li>
<li><span style="color:#006600;"> * Loads any XML document using ActiveX (for IE) or createDocumentFunction (for </span></li>
<li><span style="color:#006600;"> * other browsers)</span></li>
<li><span style="color:#006600;"> * @param {String} fileName name of the file to be loaded</span></li>
<li><span style="color:#006600;"> * @return {XMLDocument|Object}</span></li>
<li><span style="color:#006600;"> */</span></li>
<li><span style="color:#003366;">function</span> loadXML<span style="color:#009900;">(</span>fileName<span style="color:#009900;">)</span> <span style="color:#009900;">{</span> <span style="color:#006600;">// http://www.w3schools.com/xsl/xsl_client.asp </span></li>
<li> <span style="color:#003366;">var</span> xmlFile <span style="color:#339933;">=</span> <span style="color:#003366;">null</span>;</li>
<li></li>
<li> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span>window.<span style="color:#660066;">ActiveXObject</span><span style="color:#009900;">)</span> <span style="color:#009900;">{</span> <span style="color:#006600;">// IE</span></li>
<li> xmlFile <span style="color:#339933;">=</span> <span style="color:#003366;">new</span> ActiveXObject<span style="color:#009900;">(</span><span style="color:#3366cc;">&laquo;Microsoft.XMLDOM&raquo;</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span> <span style="color:#000066;">else</span> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span>document.<span style="color:#660066;">implementation</span></li>
<li> <span style="color:#339933;">&amp;&amp;</span> document.<span style="color:#660066;">implementation</span>.<span style="color:#660066;">createDocument</span><span style="color:#009900;">)</span> <span style="color:#009900;">{</span> <span style="color:#006600;">// Mozilla, Firefox, Opera, etc.</span></li>
<li> xmlFile <span style="color:#339933;">=</span> document.<span style="color:#660066;">implementation</span>.<span style="color:#660066;">createDocument</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&laquo;&raquo;</span><span style="color:#339933;">,</span><span style="color:#3366cc;">&laquo;&raquo;</span><span style="color:#339933;">,</span><span style="color:#003366;">null</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span><span style="color:#339933;">!</span>xmlFile.<span style="color:#660066;">load</span><span style="color:#009900;">)</span> <span style="color:#009900;">{</span> <span style="color:#006600;">// Safari lacks on this method,</span></li>
<li> <span style="color:#006600;">// so we make a synchronous XMLHttpRequest</span></li>
<li> <span style="color:#003366;">var</span> request <span style="color:#339933;">=</span> makeRequest<span style="color:#009900;">(</span>fileName<span style="color:#339933;">,</span> <span style="color:#003366;">null</span><span style="color:#339933;">,</span> <span style="color:#003366;">null</span><span style="color:#339933;">,</span> <span style="color:#003366;">true</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#000066;">return</span> request.<span style="color:#660066;">responseXML</span>;</li>
<li> <span style="color:#009900;">}</span></li>
<li> <span style="color:#009900;">}</span> <span style="color:#000066;">else</span> <span style="color:#009900;">{</span></li>
<li> <span style="color:#000066;">alert</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&#8216;Your browser cannot create XML DOM Documents&#8217;</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span></li>
<li> xmlFile.<span style="color:#660066;">async</span> <span style="color:#339933;">=</span> <span style="color:#003366;">false</span>;</li>
<li> <span style="color:#000066;">try</span> <span style="color:#009900;">{</span></li>
<li> xmlFile.<span style="color:#660066;">load</span><span style="color:#009900;">(</span>fileName<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span> <span style="color:#000066;">catch</span><span style="color:#009900;">(</span>e<span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> <span style="color:#000066;">alert</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&#8216;an error occured while loading XML file &#8217;</span> <span style="color:#339933;">+</span> fileName<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span></li>
<li> <span style="color:#000066;">return</span><span style="color:#009900;">(</span>xmlFile<span style="color:#009900;">)</span>;</li>
<li><span style="color:#009900;">}</span></li>
</ol>
</blockquote>
<p>В результате, функция возвращает XML-объект по заданному имени файла. Можно приступать собственно к трансформации.</p>
<h3>Преобразование через XSLT</h3>
<p>Преобразованием будет заниматься ещё одна функция, которая будет принимать в качестве аргументов пути к XML-файлу и XSL-файлу. Загружать эти файлы она будет описанной выше функцией  <tt>loadXML</tt>. А возвращать эта функция будет строку с XHTML-кодом, который можно будет вставить прямо в <tt>innerHTML</tt> нужного элемента.</p>
<p>Почему строку? Потому что метод <tt>transformFragment</tt> объекта <tt>XSLTProcessor</tt> не поддерживает рендеринг XML (<tt>xsl:output method="xml"</tt>), а поддерживает только HTML (<tt>xsl:output method="html"</tt>). В результате преобразования с <tt>xsl:output method="xml"</tt> и <tt>transformFragment</tt> генерируется корректный <tt>DocumentFragment</tt>, который, однако, при вставке в XHTML-код действует как некая XML-нода — поэтому визуально виден только, так называемый, <tt>plain text</tt>. Если вас не смущает потеря пространств имён, вы можете изменить <tt>xsl:output method</tt> на <tt>html</tt> и использовать <tt>transformFragment</tt>, добившись в результате, чтобы функция возвращала <tt>DocumentFragment</tt>.</p>
<p>В случае Internet Explorer используется функция <tt>transformNode</tt> XML-объекта, в остальных браузерах используется <tt>XSLTProcessor</tt>.</p>
<blockquote>
<ol>
<li><span style="color:#006600;">/**</span></li>
<li><span style="color:#006600;"> * Applies specified XSL stylesheet to the specified XML file and returns</span></li>
<li><span style="color:#006600;"> * the result as a string. ActiveX is used in IE, otherwise, XSLTProcessor</span></li>
<li><span style="color:#006600;"> * is used.</span></li>
<li><span style="color:#006600;"> * @param {String} xmlFileName path to the xml file to be transformed</span></li>
<li><span style="color:#006600;"> * @param {String} xslFileName path to the xsl file to be applied to the xml</span></li>
<li><span style="color:#006600;"> * @return {String} xsl transformation result as a text</span></li>
<li><span style="color:#006600;"> */</span></li>
<li><span style="color:#003366;">function</span> getStylingResult<span style="color:#009900;">(</span>xmlFileName<span style="color:#339933;">,</span> xslFileName<span style="color:#009900;">)</span> <span style="color:#009900;">{</span></li>
<li> <span style="color:#003366;">var</span> xmlContent <span style="color:#339933;">=</span> loadXML<span style="color:#009900;">(</span>xmlFileName<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#003366;">var</span> xslContent <span style="color:#339933;">=</span> loadXML<span style="color:#009900;">(</span>xslFileName<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span>window.<span style="color:#660066;">ActiveXObject</span><span style="color:#009900;">)</span> <span style="color:#009900;">{</span> <span style="color:#006600;">// IE</span></li>
<li> <span style="color:#000066;">return</span> xmlContent.<span style="color:#660066;">transformNode</span><span style="color:#009900;">(</span>xslContent<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span> <span style="color:#000066;">else</span> <span style="color:#000066;">if</span> <span style="color:#009900;">(</span>window.<span style="color:#660066;">XSLTProcessor</span><span style="color:#009900;">)</span> <span style="color:#009900;">{</span> <span style="color:#006600;">// Mozilla, Firefox, Opera, Safari etc.</span></li>
<li> <span style="color:#003366;">var</span> xsltProcessor<span style="color:#339933;">=</span><span style="color:#003366;">new</span> XSLTProcessor<span style="color:#009900;">(</span><span style="color:#009900;">)</span>;</li>
<li> xsltProcessor.<span style="color:#660066;">importStylesheet</span><span style="color:#009900;">(</span>xslContent<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#006600;">// return xsltProcessor.transformToFragment(xmlContent, document); </span></li>
<li> <span style="color:#006600;">// somehow, transformToFragment works incorrectly, recognizing the</span></li>
<li> <span style="color:#006600;">// result of transformation as xml, not html, because </span></li>
<li> <span style="color:#006600;">// xsl:output=&raquo;xhtml&raquo; is still not supported, and for xhtml</span></li>
<li> <span style="color:#006600;">// xsl:output=&raquo;xml&raquo; is used </span></li>
<li> <span style="color:#006600;">// (xsl:output=&raquo;html&raquo; strips namespaces)</span></li>
<li> <span style="color:#006600;">// see: http://osdir.com/ml/mozilla.devel.layout.xslt/2003-10/msg00008.html</span></li>
<li> <span style="color:#006600;">// also, see: https://developer.mozilla.org/en/Using_the_Mozilla_JavaScript_interface_to_XSL_Transformations</span></li>
<li> <span style="color:#003366;">var</span> resultDocument <span style="color:#339933;">=</span> xsltProcessor.<span style="color:#660066;">transformToDocument</span><span style="color:#009900;">(</span>xmlContent<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#003366;">var</span> xmls <span style="color:#339933;">=</span> <span style="color:#003366;">new</span> XMLSerializer<span style="color:#009900;">(</span><span style="color:#009900;">)</span>;</li>
<li> <span style="color:#000066;">return</span> xmls.<span style="color:#660066;">serializeToString</span><span style="color:#009900;">(</span>resultDocument<span style="color:#009900;">)</span>;</li>
<li> <span style="color:#009900;">}</span></li>
<li><span style="color:#009900;">}</span></li>
</ol>
</blockquote>
<h2>Итог</h2>
<p>Всё, весь необходимый код готов и вы можете использовать функцию <tt>getStylingResult</tt> для преобразования XML-файлов и вставки результата в XHTML. Например, таким образом:</p>
<blockquote>
<ol>
<li>document.<span style="color:#660066;">getElementById</span><span style="color:#009900;">(</span><span style="color:#3366cc;">&#8216;content&#8217;</span><span style="color:#009900;">)</span>.<span style="color:#660066;">innerHTML</span> <span style="color:#339933;">=</span></li>
<li> getStylingResult<span style="color:#009900;">(</span><span style="color:#3366cc;">&#8216;./contacts.xml&#8217;</span><span style="color:#339933;">,</span> <span style="color:#3366cc;">&#8216;./contacts.xsl&#8217;</span><span style="color:#009900;">)</span>;</li>
</ol>
</blockquote>
<p>Как итог, мы получили действительно кросс-браузерную версию обработки XML на клиенте. Спасибо за внимание.</p>
<p>(<em>Подсветка кода выполнена с помощью <a href="http://highlight.hohli.com/">Syntax Highlighter</a> от <a href="http://anton.shevchuk.name/">Антона Шевчука</a></em>)</p>
<p><strong>P.S.</strong> Статья доступна также <a href="http://shaman-sir.wikidot.com/client-xml-xslt-xhtml-browsers">в моём блоге</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/96/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=96&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2009/02/04/get-xml-get-xsl-do-xhtm/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/05/wikidot.gif" medium="image">
			<media:title type="html">This acrticle at wikidot.com</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/08/javascript.png" medium="image">
			<media:title type="html">JavaScript</media:title>
		</media:content>

		<media:content url="http://shaman-sir.wikidot.com/local--files/client-xml-xslt-xhtml-browsers/xml-schema-example.jpg" medium="image">
			<media:title type="html">XML Schema</media:title>
		</media:content>

		<media:content url="http://shaman-sir.wikidot.com/local--files/client-xml-xslt-xhtml-browsers/xml-rendering-result.jpg" medium="image">
			<media:title type="html">XML Rendering Result</media:title>
		</media:content>
	</item>
		<item>
		<title>Wikified</title>
		<link>http://shamansir.wordpress.com/2008/05/25/wikified/</link>
		<comments>http://shamansir.wordpress.com/2008/05/25/wikified/#comments</comments>
		<pubDate>Sun, 25 May 2008 15:42:57 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[планы]]></category>
		<category><![CDATA[itself]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/?p=75</guid>
		<description><![CDATA[Я тут взял, да викифицировал основные статьи из этого блога. Там, на этом Wikidot есть подсветка синтаксиса, так что код стало читать удобнее. И подготавливать статьи в wiki тоже несколько удобнее, чем в html. И ещё там всё настраивается, только вот места пока поменьше чем здесь, но мне много и не надо :). Так вот, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=75&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://wikidot.com/" title="Wikidot.com"><img src="http://shamansir.files.wordpress.com/2008/05/wikidot1.png?w=575" alt="Wikidot.com" style="border:1px dotted #000000;" /></a></p>
<p style="text-align:justify;">Я тут взял, да <a href="http://shaman-sir.wikidot.com">викифицировал</a> основные статьи из этого блога. Там, на этом <a href="http://wikidot.com">Wikidot</a> есть подсветка синтаксиса, так что код стало читать удобнее. И подготавливать статьи в <code>wiki</code> тоже несколько удобнее, чем в <code>html</code>. И ещё там всё настраивается, только вот места пока поменьше чем здесь, но мне много и не надо :).</p>
<p style="text-align:justify;">Так вот, я не буду ни в коем случае забрасывать этот блог, но статьи будут появляться там раньше, а потом уже переоформляться (из вики зачёт регэкспов да и просто копи-пэйста это сделать не так сложно) сюда. Я много раз переезжал из разных мест, но тут я всё же задержался и не думаю, что стоит бросать это место &mdash; просто будет два параллельных режима и всё.</p>
<p>Так что, если вы видите под заголовком справа кнопку <img style="border:none;position:relative;top:3px;padding:0 2px;" src="http://shamansir.files.wordpress.com/2008/05/wikidot.gif?w=16&#038;h=16" alt="Acrticle at wikidot.com" width="16" height="16" />  то это значит, что кликнув по ней вы увидите эту же статью, только викифицированную.</p>
<p>Вот так. </p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shamansir.wordpress.com/75/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shamansir.wordpress.com/75/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/75/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=75&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2008/05/25/wikified/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/05/wikidot1.png" medium="image">
			<media:title type="html">Wikidot.com</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/05/wikidot.gif" medium="image">
			<media:title type="html">Acrticle at wikidot.com</media:title>
		</media:content>
	</item>
		<item>
		<title>Trac + Subversion @ Ubuntu: Revisited</title>
		<link>http://shamansir.wordpress.com/2008/03/17/trac-subversion-ubuntu-revisited/</link>
		<comments>http://shamansir.wordpress.com/2008/03/17/trac-subversion-ubuntu-revisited/#comments</comments>
		<pubDate>Sun, 16 Mar 2008 23:12:04 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[девелопмент]]></category>
		<category><![CDATA[os]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/?p=70</guid>
		<description><![CDATA[Задача Установить на только что инсталлированный Ubuntu последнюю версию Trac, создать репозитории для нескольких проектов и настроить окружение соответственно. Структура проектов должна быть полностью корректной, установка максимально быстрой при минимальном количестве пакетов. Авторизация в репозитории и окружения Trac может быть общей, но позволяющей индивидуальную настройку для каждого проекта. Также, установка должна быть максимально независима от [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=70&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a title="This acrticle at wikidot.com" href="http://shaman-sir.wikidot.com/trac-subersion-ubuntu-revisited"><img style="float:right;border:none;" src="http://shamansir.files.wordpress.com/2008/05/wikidot.gif?w=16&#038;h=16" alt="This acrticle at wikidot.com" width="16" height="16" /></a></p>
<p><a href="http://ubuntu.com/" title="Ubuntu"><img src="http://shamansir.files.wordpress.com/2007/08/ubuntu.png?w=575" alt="Ubuntu" style="border:1px dotted #000000;" /></a> <a href="http://trac.edgewall.org/" title="Trac"><img src="http://shamansir.files.wordpress.com/2007/08/trac.png?w=575" alt="Trac" style="border:1px dotted #000000;" /></a> <a href="http://subversion.tigris.org/" title="Subversion"><img src="http://shamansir.files.wordpress.com/2007/08/svn.png?w=575" alt="Subversion" style="border:1px dotted #000000;" /></a></p>
<h5>Задача</h5>
<p style="text-align:justify;">Установить на только что инсталлированный Ubuntu последнюю версию Trac, создать  репозитории для нескольких проектов и настроить окружение соответственно. Структура проектов должна быть полностью корректной, установка максимально быстрой при минимальном количестве пакетов. Авторизация в репозитории и окружения Trac может быть общей, но позволяющей индивидуальную настройку для каждого проекта. Также, установка должна быть максимально независима от версий.</p>
<p><span id="more-70"></span></p>
<h5>Дано</h5>
<ul>
<li>Ubuntu 7.04 <i>Feisty Fawn Herd</i></li>
<li>Trac 0.11b2</li>
<li>Subversion 1.4.3</li>
<li>Два пользователя: <code>user1</code> и <code>user2</code></li>
<li>Два проекта: <code>Some Project</code> и <code>Another Project</code></li>
<li>Требуется доступ в Trac и репозиторий по адресам <code>&lt;host&gt;/localProjects</code> и <code>&lt;host&gt;/svn</code> соотвественно</li>
</ul>
<h5>Решение. Пункт 1. Установка базовых дистрибутивов, доступных в пакетах.</h5>
<p style="text-align:justify;">Для начала можно установить дистрибутивы, доступные в репозиториях Ubuntu в поддерживаемых версиях &#8211; на данный момент это <a href="http://apache.org">Apache</a> 2.2.3, <a href="http://python.org">Python</a> 2.5.1 (необходим для работы trac), <a href="http://subversion.tigris.org/">Subversion</a> 1.4.3 и <a href="http://gcc.gnu.org/">g++</a> 4.1.2 (необходим для сборки sqlite). Установим, предварительно обновив данные о пакетах:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo apt-get update
sudo apt-get install python
sudo apt-get install apache2
sudo apt-get install subversion
sudo apt-get install g++</code></pre>
<h5>Решение. Пункт 2. Установка sqlite.</h5>
<p style="text-align:justify;">Теперь необходимо собрать sqlite (легковесная база данных, в котрой будут хранится внутренние данные trac) — версия, находящая в репозитории (3.3.13) на данный момент меньше требуемой (3.3.4). Создадим каталог для временного хранения дистрибутивов и перейдём в него:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>mkdir ~/distr
cd ~/distr</code></pre>
<p style="text-align:justify;">Скачаем <a href="http://www.sqlite.org/download.html">последнюю версию</a> sqlite и установим:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>wget http://www.sqlite.org/sqlite-3.5.6.tar.gz
tar xvfz ./sqlite-3.5.6.tar.gz
mv ./sqlite-3.5.6 ./sqlite # чтобы следовать букве README-руководства
mkdir ./bld # временный каталог для скомилированных файлов
cd ./bld
../sqlite/configure
make
sudo make install
cd ..
rm -r ./bld</code></pre>
<h5>Решение. Пункт 3. Установка trac-related пакетов через easy_install.</h5>
<p style="text-align:justify;">Для Python существует утилита, облегчающая установку python-пакетов, называемых также <i>яйцами</i> (они имеют расширение *.egg). Установим её:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>wget http://peak.telecommunity.com/dist/ez_setup.py
sudo python ./ez_setup.py</code></pre>
<p style="text-align:justify;">И засчёт неё установим последние версии <a href="http://pygments.org/">Pygments</a> (0.9) (инструмент для подсветки программного кода на Python), <a href="http://genshi.edgewall.org/">Genshi</a> (0.4.4) (механизм шаблонов от создателей trac) и собственно самого <a href="http://trac.edgewall.org/">trac</a> (0.11b2):</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo easy_install Pygments
sudo easy_install Genshi
sudo easy_install Trac</code></pre>
<h5>Решение. Пункт 4. Создание репозиториев.</h5>
<p style="text-align:justify;">Создадим репозитории для наших проектов и сделаем первые коммиты, содержащие отправные точки для их структур. Все репозитории будут находиться в каталоге <code>/var/svn</code>, полностью доступном для сервера, каждый в своём подкаталоге — такой метод удобен при наличии нескольких проектов и это будет заметно в следующем пункте, на этапе настройки авторизации.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo mkdir /var/svn
sudo mkdir /var/svn/someProject
sudo mkdir /var/svn/anotherProject
cd /tmp
sudo rm -rfR * # удалить все обычные файлы
sudo rm -rfR .* # удалить все скрытые/системные файлы
mkdir /tmp/someProject
mkdir /tmp/someProject/trunk
mkdir /tmp/someProject/tags
mkdir /tmp/someProject/branches
mkdir /tmp/anotherProject
mkdir /tmp/anotherProject/trunk
mkdir /tmp/anotherProject/tags
mkdir /tmp/anotherProject/branches
sudo svnadmin create /var/svn/someProject
sudo svn import ./someProject file:///var/svn/someProject
    -m "Initial import"
sudo svnadmin create /var/svn/anotherProject
sudo svn import ./anotherProject file:///var/svn/anotherProject
    -m "Initinal import"
sudo chown -R www-data:www-data /var/svn</code></pre>
<h5>Решение. Пункт 5. Связывание apache и subversion.</h5>
<p style="text-align:justify;">Необходимо настроить доступ извне для созданных репозиториев. Для этого нужно установить модуль <code>dav_svn</code> для <code>apache2</code> и заодно, раз мы работаем с subversion, установим связку subversion c Python, для корректной работы trac с репозиториями:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo apt-get install libapache2-svn
sudo apt-get install python-subversion</code></pre>
<p style="text-align:justify;">Теперь нужно настроить установленный модуль (при установки он автоматически включается для apache, если нет — используйте <code>a2enmod dav_svn</code> по завершению настройки):</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo vi /etc/apache2/mods-available/dav_svn.conf</code></pre>
<p style="text-align:justify;">Ниже приведено точное содержимое конфигурационного файла. При обращении на путь <code>&lt;host&gt;/svn/...</code> модуль авторизации apache будет обращаться к файлу <code>/etc/apache2/dav_svn.passwd</code> за списком пользователей, а затем давать права на доступ к соответствующему проекту из файла <code>/etc/apache2/dav_svn.authz</code>. Обратите также внимание на использование <code>SVNParentPath</code> вместо <code>SVNPath</code> — таким образом subversion-модуль поймёт, что мы используем мультипроектную структуру и будет обрабатывать путь не как один общий репозиторий, а как несколько внутренних:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>&lt;Location /svn&gt;
    DAV svn
    SVNParentPath /var/svn
    AuthType Basic
    AuthName "Subversion Repository"
    AuthUserFile /etc/apache2/dav_svn.passwd
    AuthzSVNAccessFile /etc/apache2/dav_svn.authz
    Require valid-user
&lt;/Location&gt;</code></pre>
<p style="text-align:justify;">Создадим соответствующих пользователей в файлах авторизации. Используйте пароли попроще для проверки и не забудьте их потом поменять:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo htpasswd -c /etc/apache2/dav_svn.passwd user1
sudo htpasswd /etc/apache2/dav_svn.passwd user2</code></pre>
<p style="text-align:justify;">Создадим файл аутентификации:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;">sudo vi /etc/apache2/dav_svn.authz</pre>
<p style="text-align:justify;">В открытым файле опишем права доступа (на чтение — &laquo;<code>r</code>&raquo; и на запись — &laquo;<code>w</code>&laquo;) пользователей в соответствующие репозитории:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>[/]
user1=r
user2=r

[/someProject]
user1=rw
user2=r

[/anotherProject]
user1=r
user2=rw</code></pre>
<h5>Решение. Пункт 6. Создание окружений trac.</h5>
<p style="text-align:justify;">Создадим каталог, в котором будут находиться окружения для соответствующих проектов.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo mkdir /var/trac
cd /var/trac</code></pre>
<p style="text-align:justify;">Теперь создадим для каждого из них, по очереди, окружение:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo trac-admin someProject initenv
sudo trac-admin anotherProject initenv</code></pre>
<p style="text-align:justify;">Имена проектов остаются на ваше усмотрение, тип репозиториев — по умолчанию <code>svn</code> (просто нажать Enter), путь к базе общий, по умолчанию (<code>sqlite:db/trac.db</code>, аналогично), пути к репозиториям: <code>/var/svn/someProject</code> и <code>/var/svn/anotherProject</code> соответственно.</p>
<p style="text-align:justify;">Дадим права apache пользоваться этим каталогом.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo chown -R www-data:www-data /var/trac</code></pre>
<h5>Решение. Пункт 7. Связывание apache и trac.</h5>
<p style="text-align:justify;">Есть несколько вариантов такого связывания, мы остановимся на быстром, но надёжном способе — через <code>mod_python</code> (<a href="http://trac.edgewall.org/wiki/TracInstall#WebServer">описания способов</a> на сайте trac). Для этого модуль нужно установить (также, если он не включился после установки, по завершению настройки используйте <code>a2enmod mod_python</code>):</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo apt-get install libapache2-mod-python</code></pre>
<p style="text-align:justify;">Настроим доступ к окружениям trac:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo vim /etc/apache2/sites-available/trac</code></pre>
<p style="text-align:justify;">Эта настройка специфична для использования <code>mod_python</code> (<a href="http://trac.edgewall.org/wiki/TracModPython">руководство</a> на сайте trac, см. <a href="http://trac.edgewall.org/wiki/TracInstall#WebServer">описания</a>, если необходимы другие способы настройки). Обработчиком обращений по адресу <code>&lt;host&gt;/localProjects</code> выступит модуль, он будет рассматривать каталог <code>/var/trac/</code> как корень нескольких проектов и содаст страницу с их списком (редактируемый шаблон можно найти внутри исходников trac), аналогично принципам <code>SVNParentPath</code>, <code>URI</code> передаётся в код trac. Запросы на вход будут обрабатываться по пользователям из того же <code>passwd</code> файла, из которого берёт их список читает subversion, а их права на действия в окружениях trac раздаются через <code>trac-admin</code> или в GUI-версии TracAdmin, доступной для аминистраторов окружений (будьте внимательны, пользователи создаваемые через интерфейс также добавляются в этот файл и доступны к использованию для настройки авторизации в subversion через <code>authz</code>-файл (по умолчанию у них нет никаких прав)) .</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>&lt;Location /localProjects&gt;
   SetHandler mod_python
   PythonInterpreter main_interpreter
   PythonHandler trac.web.modpython_frontend
   PythonOption TracEnvParentDir /var/trac
   PythonOption TracUriRoot /localProjects
&lt;/Location&gt;

&lt;LocationMatch /localProjects/[^/]+/login&gt;
   AuthType Basic
   AuthName "Local Projects"
   AuthUserFile /etc/apache2/dav_svn.passwd
   Require valid-user
&lt;/LocationMatch&gt;</code></pre>
<p style="text-align:justify;">Теперь заменим сайт по умолчанию для apache на сайт trac:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo a2dissite default
sudo a2ensite trac</code></pre>
<p style="text-align:justify;">Дадим пользователям права администратов в окружениях trac, в соотвествии с правами на репозиторий, теперь у них, у каждого в своём проекте, будет веб-интерфейс для полной настройки trac.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo trac-admin someProject permission add user1 TRAC_ADMIN
sudo trac-admin anotherProject permission add user2 TRAC_ADMIN</code></pre>
<h5>Решение. Заключение.</h5>
<p style="text-align:justify;">Осталось перезагрузить сервер, (принудительная перезагрузка настроек: <code>force-reload</code>) и проверить адреса <code>&lt;host&gt;/localProjects</code> и <code>&lt;host&gt;/svn/someProject</code> и <code>&lt;host&gt;/svn/anotherProject</code>, попробовав авторизироваться разными пользователями.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>sudo /etc/init.d/apache2 restart</code></pre>
<p style="text-align:justify;">Если при установке появились какие-либо проблемы и ничего не помогает, попробуйте ознакомиться с <a href="http://shamansir.wordpress.com/2006/12/16/trac-subversion-ubuntu-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%b5%d1%81%d0%bd%d0%b0%d1%8f-%d0%b7%d0%b0%d0%b1%d0%b0%d0%b2%d0%b0-%d0%bd%d0%b0-%d0%b4%d0%b5%d0%bd%d1%8c/">предыдущей статьёй</a> (но она несколько более сумбурна и менее структурирована) или опишите проблему(-мы) в комментариях — постараюсь реагировать быстро.</p>
<h5>Примечание A. О добавлении проектов.</h5>
<p style="text-align:justify;">Добавление проектов в будущем требует лишь нескольких шагов — создание базовой структуры первым коммитом в какой-либо подкаталог <code>/var/svn</code>, опциональное добавление новых пользователей в <code>htpasswd</code>-файл, настройка прав доступа в <code>authz</code>-файле, создание окружения trac в соответствующем подкталоге <code>/var/trac</code> через <code>trac initenv</code>, опциональная выдача trac-прав новым пользователям и проверка, что apache имеет доступ к созданным каталогам.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shamansir.wordpress.com/70/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shamansir.wordpress.com/70/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/70/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/70/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/70/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/70/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/70/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/70/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/70/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/70/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/70/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/70/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/70/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/70/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/70/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/70/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=70&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2008/03/17/trac-subversion-ubuntu-revisited/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/05/wikidot.gif" medium="image">
			<media:title type="html">This acrticle at wikidot.com</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/08/ubuntu.png" medium="image">
			<media:title type="html">Ubuntu</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/08/trac.png" medium="image">
			<media:title type="html">Trac</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/08/svn.png" medium="image">
			<media:title type="html">Subversion</media:title>
		</media:content>
	</item>
		<item>
		<title>[g]Vim в режиме Python: Рекомпиляция в Windows</title>
		<link>http://shamansir.wordpress.com/2008/03/15/gvim-python-windows-compilation/</link>
		<comments>http://shamansir.wordpress.com/2008/03/15/gvim-python-windows-compilation/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 13:32:16 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[девелопмент]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[os]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/?p=66</guid>
		<description><![CDATA[Введение Редактор Vim наиболее известен среди разработчиков в системах Unix — конкурент emacs, что-то вроде консольного IDE — этот редактор при должной сноровке и настройке (мне кажется, сноровке несколько меньшей и настройке более очевидной чем в emacs, но у последнего также есть мощная мультифункциональность — выбор за программистом) способен убыстрить и упростить многие процессы на [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=66&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a title="This acrticle at wikidot.com" href="http://shaman-sir.wikidot.com/vim-python-windows-compilation"><img style="float:right;border:none;" src="http://shamansir.files.wordpress.com/2008/05/wikidot.gif?w=16&#038;h=16" alt="This acrticle at wikidot.com" width="16" height="16" /></a></p>
<p><a href="http://www.vim.org/" title="Vim"><img src="http://shamansir.files.wordpress.com/2008/03/wordpress-vim.png?w=575" alt="Vim" style="border:1px dotted #000000;" /></a> <a href="http://www.python.org" title="Python"><img src="http://shamansir.files.wordpress.com/2007/08/python.png?w=575" alt="Python" style="border:1px dotted #000000;" /></a> <a href="http://www.microsoft.com/windows/" title="Windows"><img src="http://shamansir.files.wordpress.com/2008/03/wordpress-windows.png?w=575" alt="Windows" style="border:1px dotted #000000;" /></a></p>
<h5>Введение</h5>
<p style="text-align:justify;">Редактор <code>Vim</code> наиболее известен среди разработчиков в системах <code>Unix</code> — конкурент <code>emacs</code>, что-то вроде консольного IDE — этот редактор при должной сноровке и настройке (мне кажется, сноровке несколько меньшей и настройке более очевидной чем в <code>emacs</code>, но у последнего также есть мощная мультифункциональность — выбор за программистом) способен убыстрить и упростить многие процессы на этапах разработки не в ущерб таким удобствам как, например, авто-дополнение и навигация по проекту. Однако, если вы собираетесь использовать его для разработки на <code>Python</code> со всеми подобными удобствами — потребуются некоторые усилия: а именно, перекомпиляция&#8230;</p>
<p><span id="more-66"></span></p>
<p>Приведу несколько ссылок по теме:</p>
<ul>
<li><a href="http://mgul.ac.ru/~t-alex/Linux/Vim-Color-Editor-HOW-TO/Vim-9.html">Vim How-To</a> — Работа в vim. Небольшое, но грамотное, вводное руководство. (<a href="http://mgul.ac.ru/~t-alex/Linux/Vim-Color-Editor-HOW-TO/Vim.html">полное содержание</a>, содержит <a href="http://mgul.ac.ru/~t-alex/Linux/Vim-Color-Editor-HOW-TO/Vim-10.html">справочник по командам</a>)</li>
<li><a href="http://www.viemu.com/a_vi_vim_graphical_cheat_sheet_tutorial.html">Набор изображений</a> для быстрого и наглядного изучения сочетаний клавиш. <i>(англ.)</i></li>
<li><a href="http://allaboutvim.blogspot.com/2007/12/vim-python.html">Настройка Vim для работы с Python</a> — статья с подробным рассмотрением настройки и упоминанием всех необходимых дополнений</li>
<li><a href="http://users.skynet.be/antoine.mechelynck/vim/compile.htm">Компилирование [g]Vim для Windows</a> — статья, послужившая основой для написания той, которую вы читаете. <i>(англ.)</i></li>
<li><a href="http://people.smu.edu/jrobinet/howto/compile-vim-on-windows.asp">Альтернативная статья</a> на ту же тему — более краткая, но о Python 2.5</li>
<li><a href="http://www.petersblog.org/node/461">Некоторые заметки</a> о работе c Python в редакторе Vim. <i>(англ.)</i></li>
</ul>
<h5>Версии</h5>
<p style="text-align:justify;">Компиляция производилась с использованием <code>[g]Vim 7.1</code>, <code>Python 2.5.2</code>, <code>Tcl 8.5.1</code>, <code>Cygwin 1.5.25-11</code> на <code>Windows XP SP2</code>, но сценарий при этом должен быть насколько возможно независим от версий.</p>
<h5>Установка необходимых программ</h5>
<p style="text-align:justify;">Итак, подготовка. Нужно заранее установить сам язык — <a href="http://www.python.org/download/">Python</a> (если он не установлен) и, если вы собираетесь использовать Tcl — соответственно <a href="http://www.tcl.tk/software/tcltk/">Tcl/Tk</a> (с некоторого времени язык стал владением ActiveState: можно <a href="http://www.activestate.com/store/activetcl">скачать бесплатный ActiveTcl</a>). При компиляции используются динамические библиотеки соответствующих языков.</p>
<p style="text-align:justify;">Для работы с архивами и собственно компиляции нам понадобится эмулятор Unix-утилит под Windows &#8211; это <a href="http://cygwin.com/">Cygwin</a>. В нём существуют и компилятор <code>gcc</code>, и необходимые для компиляции файлы (есть путь с компилятором Borland, но он несколько сложнее). <a href="http://cygwin.com/setup.exe">Файл установки</a> работает немного непривычным образом — скачивая и файлы установки и пакеты уже после вашего выбора (если вы выберете установку из Интернет, которая в первый раз в любом случае необходима) — при этом для обновления или до/переустановки пакетов вы, возможно, будете возвращаться к инсталлятору довольно-таки часто. Тем не менее, чтобы установить минимальный набор необходимых для нашего случая вещей — нужно отметить лишь пару пунктов: после выбора способа установки (на данный момент наиболее стабильно для меня работало зеркало <code>ftp://mirror.switch.ch</code> (хотя буквально в эти секунды его исключили из списка официальных зеркал): если будут ошибки закачки — вас снова вернут к выбору зеркала) в списке выбора пакетов убедитесь что вы находитесь в режиме <code>Category</code> (переключив его, если надо, кнопкой <code>View</code> вверху), рядом с пунктом <code>All</code>, несколько раз потыкав надпись <code>Default</code> поменяйте её на <code>Uninstall</code> (чтобы не устанавливать ненужных пакетов) и выберите следующие пункты — <code>Utils/patch</code>, <code>Devel/gcc-g++</code>, <code>Devel/make</code>, <code>System/man</code> и <code>Devel/gcc-mingw</code> (последний, возможно, будет уже заранее выбран, значит они уже исправили одну проблему, которая отражалось на удачной компиляции :) ) — при этом у вас автоматически станут выбраны некоторые другие относительно необходимые пакеты (можно перепроверить): <code>Shells/bash</code>, <code>Utils/bzip2</code> и <code>Devel/mingw-runtime</code> (последний, тем не менее, безмерно важен). Также советую установить <code>Web/wget</code> для того, чтобы облегчить в дальнейшем закачку патчей. Всё, можно жать установку.</p>
<p style="text-align:justify;">Затем нужно, собственно, установить <a href="http://www.vim.org/download.php#pc">gVim</a>. Можно заранее его настроить под Python, руководствуясь <a href="http://allaboutvim.blogspot.com/2007/12/vim-python.html">статьей</a>, упомянутой выше — тогда при попытке подключения авто-дополнения Vim будет сообщать о необходимости перекомпиляции с ключом <code>+python</code>, что мы и планируем сделать.</p>
<h5>Подготовка</h5>
<p style="text-align:justify;">Запустите <code>cmd</code> и убедитесь, что в переменных окружения <code>USERNAME</code> и <code>USERDOMAIN</code> содержатся ваше имя и имя вашего компьютера и домена соответственно (<code>echo %username%@%userdomain%</code>), а <code>PATH</code> содержит путь к <code>bin</code>-каталогу Cygwin. <code>HOME</code> может  указывать на ваш каталог &laquo;Мои документы&raquo; (туда, где находится ваш файл настройки vim — <code>vimrc</code>), а <code>VIM</code> — на месторасположение установленного, рабочего редактора vim, желательно в формате <code>8.3</code> (напр.: <code>C:PROGRA~1VIM</code>). Значения переменных можно изменять в диалоге, расположенном здесь: <i>Мой компьютер → Свойства → Дополнительно → Переменные среды</i>.</p>
<p style="text-align:justify;">Не менее, а даже более нам необходимы исходники, поэтому <a href="ftp://ftp.vim.org/pub/vim/unix/">скачиваем их</a> для соответствующей установленной версии (будьте внимательны — именно исходники для Unix, даже при компиляции под Win32) (по предыдущей ссылке также можно скачать файлы для отладки, но отлаживание в этой статье не рассматривается и в их присутствии нет необходимости). Поверх этих исходников нужно добыть дополнение для Windows (<code>-extra</code>) и файлы языков (<code>-lang</code>) соответствующей версии <a href="ftp://ftp.vim.org/pub/vim/extra/">отсюда</a>.</p>
<p style="text-align:justify;">Также, если вы используете стабильный релиз и хотите заодно установить новейшие патчи — за файлами патчей обращайтесь <a href="ftp://ftp.vim.org/pub/vim/patches/7.1/">сюда</a> (исправьте номер версии в ссылке, если нужно). Здесь есть некоторая проблема, поскольку файлы патчей упаковываются в один только при достижении сотни (001-100, 101-200 и т.д.), поэтому если их, например, 275 — последние 75 файлов придётся закачивать руками или написав batch-скрипт с использованием <code>telnet</code>. Однако, у нас уже установлен <code>cygwin</code>, поэтому можно создать <code>.sh</code>-скрипт, выполняющий те же функции через <code>wget</code>, выглядеть это может примерно так:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>#!/bin/bash
PATCHES_DOWNLOAD_PATH=ftp://ftp.vim.org/pub/vim/patches
PATCHES_VER=7.1
wget $PATCHES_DOWNLOAD_PATH/$PATCHES_VER/$PATCHES_VER.001-100.gz
wget $PATCHES_DOWNLOAD_PATH/$PATCHES_VER/$PATCHES_VER.101-200.gz

for i in `seq 201 278`;
do
	wget $PATCHES_DOWNLOAD_PATH/$PATCHES_VER/$PATCHES_VER.$i
done</code></pre>
<p style="text-align:justify;">Теперь займёмся расположением исходников в виде, удобном для компиляции.</p>
<p style="text-align:justify;">Архивы с исходником, <code>-extra</code> и <code>-lang</code> нужно распаковать (по очереди, с заменой более старых файлов) в какой-либо каталог с сохранением структуры (пусть в нашем случае это будет <code>C:/devel/vim-src/vim71</code>), в нём должны содержаться каталоги <code>/doc</code>, <code>/nsis</code>, <code>/src</code>, <code>/farsi</code> и т.д.. В распаковке вам поможет или <code>bzip2</code> из Cygwin, или встроенный архиватор файлового менеджера <a href="http://www.ghisler.com/">Total Commander</a> или <a href="http://www.7-zip.org/">архиватор 7-zip</a> или любой другой архиватор, поддерживающий архивы <code>.tar.gz</code> :).</p>
<p style="text-align:justify;">В подкаталог <code>/runtime</code> можно положить файлы <code>.vim</code>, каталоги <code>/doc</code> и <code>/plugins</code> из рабочей версии вашего редактора vim — тогда они будут пропатчены соответственно, если вы выбрали путь компилирования с патчами. Патчи при этом можно положить в каталог <code>/patches</code>.</p>
<h5>Компиляция</h5>
<p style="text-align:justify;">Для того, чтобы установить патчи, нужно выполнить над каждым из них команду <code>patch</code> из набора Cygwin, предварительно распаковав архивы файлов с сотнями патчей. В этом случае я воспользовался <code>.bat</code>-файлом вместо <code>.sh</code> скрипта (номера патчей, конечно, нужно, поправить на соответствующие вашему набору):</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>@ECHO off
ECHO changing directory to parent...

CD ..

ECHO -------------------- %Date% -------------------- &gt;&gt; patching-src.log

ECHO %CD%: applying first 200 patches

patch -p0 &lt; patches/7.1.001-100 &gt;&gt; patching-src.log 2&gt;&amp;1
patch -p0 &lt; patches/7.1.101-200 &gt;&gt; patching-src.log 2&gt;&amp;1

ECHO %CD%: applying the last patches

FOR /L %%B IN (201,1,278) DO
    patch -p0 &lt; patches/7.1.%%B &gt;&gt; patching-src.log 2&gt;&amp;1

ECHO Finished

PAUSE

@ECHO on</code></pre>
<p style="text-align:justify;">Этот файл нужно положить в каталог <code>/patches</code> и после корректировки выполнить (убедитесь, что вся описанная выше структура дерева исходников сформирована): в корне исходников будет создан файл <code>patching-src.log</code>, в котором можно проследить результаты прошедшего патчинга. Если утилита <code>patch</code> не была найдена, проверьте <code>PATH</code> на наличие пути к Cygwin. Если некоторое (небольшое) количество файлов не было найдено и пропатчено — можно сильно не беспокоится, это в основном файлы для XWindow-версии.</p>
<p style="text-align:justify;">Теперь можно перейти непосредственно к компиляции из консоли Cygwin. Для этого необходимо удачно выполнить лишь три команды — перейти в каталог с исходниками (cygwin монтирует ваши диски в точке <code>/cygdrive/</code>: подставьте корректные пути к вашей установке Python и Tcl а также их корректные версии, а если вы не компилируете версию для Tcl — просто уберите соответствующие параметры) и создать файлы <code>vim.exe</code> (консольная версия) и <code>gvim.exe</code> (GUI-версия):</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>$ cd /cygdrive/c/devel/vim-src/vim71
$ make -B -f Make_cyg.mak GUI=no
    PYTHON=/cygdrive/c/devel/Python PYTHON_VER=25 DYNAMIC_PYTHON=yes
    TCL=/cygdrive/c/devel/Tcl TCL_VER=85 DYNAMIC_TCL=yes vim.exe
$ make -B -f Make_cyg.mak OLE=yes
    PYTHON=/cygdrive/c/devel/Python PYTHON_VER=25 DYNAMIC_PYTHON=yes
    TCL=/cygdrive/c/devel/Tcl TCL_VER=85 DYNAMIC_TCL=yes gvim.exe</code></pre>
<p style="text-align:justify;">На предупреждения и даже некоторые ошибки, если они относятся к Python или Tcl и если процесс продолжается, а в результате <code>.exe</code>-файлы созданы, можно не обращать внимания. Если всё завершилось удачно, то в каталоге <code>/src</code> вы найдёте оба <code>.exe</code>-файла. Сделайте бэкап существующих файлов в рабочем, установленном vim (например, <code>vim.exe.bak</code> и <code>gvim.exe.bak</code>) и замените их только что скомпилированными. Если вы применяли патчи, то верните обратно <code>*.vim</code> файлы, каталоги <code>/doc</code> и <code>/plugins</code> из каталога <code>/runtime</code>, предварительно сделав бэкапы и для них и заменяя старые версии. После этого запустите gVim и vim из папки рабочего vim, проверьте версию и опции компилирования там же на присутствие <code>+python</code> — в большинстве случаев всё должно сложиться удачно.</p>
<h5>Возможные ошибки</h5>
<p style="text-align:justify;">В процессе компилирования мне встретилось две ошибки: <code>cannot exec `cc1': No such file or directory</code> и <code>ld: cannot find -lgcc</code>. Обе они <a href="http://www.mail-archive.com/cygwin@cygwin.com/msg10910.html">известны авторам</a> Cygwin, однако в моём случае в скачанных мной версиях они ещё не были решены. Первая временно решается предварительным (перед компиляцией) добавлением каталога с исполняемым файлом <code>cc1.exe</code> в локальный <code>PATH</code> cygwin:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>$ PATH=$PATH:/cygdrive/c/devel/cygwin/lib/gcc/i686-pc-cygwin/3.4.4</code></pre>
<p style="text-align:justify;">Вторая решается так, как должна была решаться и первая — установкой <code>Devel/gcc-mingw</code> (её обещали автоматической при выборе <code>gcc</code> в будущем) при установке Cygwin. При этом важно установить пакеты одновременно, поэтому если ошибка всё равно появляется — попробуйте выбрать режим <code>Reinstall</code> в установщике Cygwin в том месте, где до этого вы выбирали режим <code>Uninstall</code> и установите Cygwin заново.</p>
<h5>Настройка Vim для Python</h5>
<p>(<b>Upd.</b>)</p>
<p style="text-align:justify;">На основе <a href="http://allaboutvim.blogspot.com/2007/12/vim-python.html">этой статьи</a> я создал пак (взять можно <a href="http://shaman-sir.by.ru/files/vimfiles.zip">здесь</a>) из последних версий упомянутый в ней плагинов (<a href="http://allaboutvim.blogspot.com/2007/07/projecttargz-ide.html">Project</a>, PythonComplete, NERD_Commenter, <a href="http://allaboutvim.blogspot.com/2007/08/vcscommandvim-svn_09.html">VCSCommand</a>, RunScript и TagList плюс, поверх — <a href="http://www.vim.org/scripts/script.php?script_id=850">PyDiction</a>) + минимальной настройки (в <code>ftplugin/python.vim</code>, практически идентичный соответствующему в статье (изменённая функция TabWrapper + другой способ подключения словаря) &#8211; только общепринятые стандарты, omni completion повешен на Tab). Содержимое требуется распаковать в каталог <code>&lt;путь_к_установленному_vim&gt;vimfiles</code>. Для плагина taglist потребуется скачать ctags <a href="http://prdownloads.sourceforge.net/ctags/ec57w32.zip">отсюда</a>, и распаковав полученный архив в некоторый каталог, добавить путь к нему в переменную окружения <code>PATH</code>. Затем нужно запустить vim и выполнить команду:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>:helptags $VIMvimfilesdoc</code></pre>
<p style="text-align:justify;">После этого можно будет использовать команду <code>:help &lt;название_плагина&gt;</code> для получения документации по соответствующему плагину.</p>
<p style="text-align:justify;">Обычное автодополнение при использовании настроек из пакета работает по <code>Tab</code>, дополнение по контексту (omni completion) — по <code>Ctrl+Enter</code> и <code>Ctrl+Space</code>, а дополнение по ключевым словам и модулям — по <code>Ctrl+Tab</code> (при большом количестве вариантов словарь загружается относительно долго, поэтому намеренно установлено не очень удобное сочетание).</p>
<p style="text-align:justify;">Для того, чтобы вставлять <a href="http://www.python.org/dev/peps/pep-0263/">предлагаемые</a> по спецификации строки в заголовки python-файлов при создании, добавьте нижеприведённый код в файл <code>&lt;путь_к_установленному_vim&gt;_vimrc</code>  (строка filename добавлена для демонстрации возможности добавления имени файла):.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>function! BufNewFile_PY()
   0put = '#!/usr/bin/env python'
   1put = '#-*- coding: utf-8 -*-'
   $put = '#-*- filename: ' . expand('') . ' -*-'
   $put = ''
   $put = ''
   normal G
endfunction

autocmd BufNewFile *.py call BufNewFile_PY()</code></pre>
<p style="text-align:justify;">&#8230;Вот теперь можно c чрезвычайным удобством программировать на Python.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shamansir.wordpress.com/66/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shamansir.wordpress.com/66/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/66/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=66&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2008/03/15/gvim-python-windows-compilation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/05/wikidot.gif" medium="image">
			<media:title type="html">This acrticle at wikidot.com</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/03/wordpress-vim.png" medium="image">
			<media:title type="html">Vim</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/08/python.png" medium="image">
			<media:title type="html">Python</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/03/wordpress-windows.png" medium="image">
			<media:title type="html">Windows</media:title>
		</media:content>
	</item>
		<item>
		<title>Новые продукты</title>
		<link>http://shamansir.wordpress.com/2008/02/02/new-products/</link>
		<comments>http://shamansir.wordpress.com/2008/02/02/new-products/#comments</comments>
		<pubDate>Sat, 02 Feb 2008 07:56:09 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[продукты]]></category>
		<category><![CDATA[itself]]></category>
		<category><![CDATA[japanese]]></category>
		<category><![CDATA[сцылки]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/?p=62</guid>
		<description><![CDATA[Закончил перевод основной части учебника по Python 2.5 (пока без краткого обзора по библиотекам). Перевод пока довольно-таки черновой, в некоторых местах вычитка была только на уровне стилистики и грамотности. Сам источник, к сожалению, тоже часто меняет стиль повествования. Однако, в ближайшее время (в течение трёх-четырёх дней) проведу полную вычитку и попробую продолжить дальше (учебник по [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=62&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://python.org/" title="Python"><img src="http://shamansir.files.wordpress.com/2007/08/python.png?w=575" alt="Python" style="border:1px dotted #000000;" /></a> <a href="http://en.wikipedia.org/wiki/Japan" title="Japan"><img src="http://shamansir.files.wordpress.com/2007/12/wordpress-japan.jpg?w=575" alt="Japan" style="border:1px dotted #000000;" /></a></p>
<p>Закончил перевод основной части <a href="http://ru.wikibooks.org/wiki/%D0%A3%D1%87%D0%B5%D0%B1%D0%BD%D0%B8%D0%BA_Python_2.5">учебника по Python 2.5</a> (пока без краткого обзора по библиотекам). Перевод пока довольно-таки черновой, в некоторых местах вычитка была только на уровне стилистики и грамотности. Сам <a href="http://docs.python.org/tut/tut.html">источник</a>, к сожалению, тоже часто меняет стиль повествования. Однако, в ближайшее время (в течение трёх-четырёх дней) проведу полную вычитку и попробую продолжить дальше (<a href="http://docs.python.org/dev/3.0/tutorial/index.html">учебник по Python 3.0</a> не сильно отличается, поэтому в него нужно будет внести только различия).</p>
<p>Также, благо есть повод, в разделе &laquo;<a href="http://shamansir.wordpress.com/%D0%9F%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B/">Продукты</a>&raquo; доступен &laquo;<a href="http://shaman-sir.by.ru/filed-art.html">Краткий справочник по японскому языку</a>&raquo; (также <a href="http://torrents.ru/forum/viewtopic.php?t=681498">выложен на торренте</a>), который ненароком вышел в 350 страниц толщиной и содержит больше информации, чем иногда содержат учебники.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shamansir.wordpress.com/62/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shamansir.wordpress.com/62/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/62/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=62&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2008/02/02/new-products/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/08/python.png" medium="image">
			<media:title type="html">Python</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/12/wordpress-japan.jpg" medium="image">
			<media:title type="html">Japan</media:title>
		</media:content>
	</item>
		<item>
		<title>Java + JSON. Пути к дружбе.</title>
		<link>http://shamansir.wordpress.com/2007/12/11/java-json-ways-to-the-friendship/</link>
		<comments>http://shamansir.wordpress.com/2007/12/11/java-json-ways-to-the-friendship/#comments</comments>
		<pubDate>Tue, 11 Dec 2007 00:13:43 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[ajax]]></category>
		<category><![CDATA[j2ee]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[json]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/2007/12/11/java-json-%d0%9f%d1%83%d1%82%d0%b8-%d0%ba-%d0%b4%d1%80%d1%83%d0%b6%d0%b1%d0%b5/</guid>
		<description><![CDATA[Введение Спешу поделиться результатами небольшого исследования, оказавшегося необходимым для текущего проекта. Рассматривается возможность связки Java и JSON, её преимущества и недостатки. Я расскажу о практической части, о теории больше поведают нижеприведённые ссылки (англ.). Mastering JSON — самая приятная статья по JSON, описывающая все основные принципы и дополнительные возможности Использование JSON для передачи данных AJAX&#8217;ом в [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=55&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a title="This acrticle at wikidot.com" href="http://shaman-sir.wikidot.com/java-and-json"><img style="float:right;border:none;" src="http://shamansir.files.wordpress.com/2008/05/wikidot.gif?w=16&#038;h=16" alt="This acrticle at wikidot.com" width="16" height="16" /></a></p>
<p><a href="http://java.sun.com" title="Java"><img src="http://shamansir.files.wordpress.com/2007/08/java.png?w=575" alt="J2EE" style="border:1px dotted #000000;" /></a> <a href="http://json.org" title="JSON"><img src="http://shamansir.files.wordpress.com/2007/12/wordpress-json.png?w=575" alt="JSON" style="border:1px dotted #000000;" /></a></p>
<h5>Введение</h5>
<p style="text-align:justify;">Спешу поделиться результатами небольшого исследования, оказавшегося необходимым для текущего проекта. Рассматривается возможность связки <code>Java</code> и <code>JSON</code>, её преимущества и недостатки. Я расскажу о практической части, о теории больше поведают нижеприведённые ссылки (<i>англ.</i>).</p>
<ul>
<li><a href="http://www.hunlock.com/blogs/Mastering_JSON_(_JavaScript_Object_Notation_)">Mastering JSON</a> — самая приятная статья по JSON, описывающая все основные принципы и дополнительные возможности</li>
<li><a href="http://www.ibm.com/developerworks/xml/library/wa-ajaxintro10/">Использование JSON для передачи данных AJAX&#8217;ом</a> в статье от IBM</li>
<li><a href="http://www.json.org/js.html">Описание</a> связи JSON и JavaScript на официальном сайте</li>
<li><a href="http://json.org/java/simple.txt">Краткое описание</a> скрещивания JSON и Java на официальном сайте</li>
<li><a href="http://json.org/java/">Java-классы</a> на официальном сайте</li>
<li><a href="http://www.ibm.com/developerworks/library/j-ajax2/">Способы сериализации</a> Java-объектов в статье от IBM</li>
<li><a href="http://twit88.com/blog/2007/11/20/serialize-java-object-to-json-string/">И ещё</a> о сериализации JSON-объектов в строку</li>
<li><a href="http://jsontools.berlios.de/">JSONTools</a> для Java</li>
</ul>
<p style="text-align:justify;">Если кратко — <code>JSON</code> (JavaScript Object Notation) не является ничем более сложным, чем описано в его названии. Если вы можете описать сложно-структурированный объект на <code>JavaScript</code> — то о клиентской стороне <code>JSON</code> вы знаете практически всё. Серверная часть JSON занимается тем, что принимает каким-либо способом объект, записанный в нотации <code>JavaScript</code> и разворачивает данные таким образом (наверное можно сказать, десериализует), чтобы они стали доступны (или хотя бы понятны :) ) остальной части кода.</p>
<p><span id="more-55"></span></p>
<p style="text-align:justify;">Не скажу корректно о других языках, но для <code>Java</code> код приёма объекта вам придётся написать самим (если только я не пропустил что-то очевидное) — ну и это не так сложно, поскольку всё необходимое <a href="http://json.org/java/">для разворачивания объекта</a> доступно на <a href="http://json.org">сайте <code>JSON</code></a>. Ммм, я сказал только &laquo;разворачивания&raquo;? Простите, и сворачивания тоже. Засчёт приведённого кода вы можете, например, создать <code>Java</code>-проекцию объекта в <code>JavaScript</code>-нотации (далее — <code>JSON</code>-объект) из <code>JavaBean</code>&#8216;а (с некоторыми оговорками, о которых ниже), из <code>java.util.Map</code>, или, собственно, из строки в этой нотации.</p>
<p style="text-align:justify;">Я не буду приводить примеров объектов на <code>JSON</code>, их доступно изрядно по ссылкам выше, да и зная <code>JavaScript</code>, как я уже говорил — вы знаете <code>JSON</code>. Обращу ваше внимание на то, что с передачей <code>JSON</code>-объектов следует быть осторожными и всё время помнить, что недоброжелатель, знающий серверные технологии и <code>JavaScript</code>, если захочет — эту лазейку, наверное, найдёт в первую очередь. Вспоминайте ваши любимые методы <code>JavaScript</code> и <code>Java</code>-секьюрности — это несколько сторонняя тема, об этом я здесь рассказывать не буду. И, передача JSON-объектов — это ещё и <a href="http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html">протокол</a>.</p>
<h5>Описание</h5>
<p style="text-align:justify;">Итак, практика. Я выбрал путь общего <code>Java</code>-сервлета для принятия (или раздачи) всех <code>JSON</code>-объектов в приложении и менеджера, ему их подготавливающего (или от него их принимающего). Для того, чтобы было легче создавать <code>JSON</code>-объекты на основе <code>Java</code>-объектов я выбрал путь <code>JavaBean</code>&#8216;ов, <code>JSON</code> для <code>Java</code> умеет на их основе (засчет геттеров) создавать <code>JSON</code>-объект, а нам достаточно написать код для обратного действия. Для объектов со сложной структурой наверняка понадобится эти методы переопределять, поэтому я выделил их в отдельный абстрактный класс, который должен стать отцом для всех объектов, которые будут передаваться между сервером и клиентом. В качестве бонуса, в конце статьи представлены диаграмма классов и диаграмма последовательностей этой небольшой конструкции.</p>
<h5>Процесс</h5>
<p style="text-align:justify;">В первую очередь соберём <code>jar</code>-библиотеку <code>JSON</code>, поскольку для <code>Java</code> этот пакет поставляется <a href="http://www.json.org/java/json.zip">в исходниках</a> (описание сборки позаимствовано <a href="http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Integrate;action=display;num=1163101573">отсюда</a> и вы можете спокойно пропустить эту часть, если свободно собираете <code>jar</code>&#8216;ы из исходников или вам это не требуется):</p>
<ol>
<li>Сохраните <a href="http://www.json.org/java/json.zip">пакет</a> в какой-либо каталог, который будет далее называться <code>%DOWNLOAD_HOME%</code></li>
<li>Распакуйте его и убедитесь, что структура каталогов (<code>/org/json/</code>) не изменилась.</li>
<li>Перейдите в каталог <code>%DOWNLOAD_HOME%/org/json/</code></li>
<li>Скомпилируйте классы командой <code>javac *.java</code></li>
<li>Вернитесь в каталог <code>%DOWNLOAD_HOME%</code></li>
<li>Командой <code>jar -cvf json.jar orgjson*.class</code> создайте jar-архив.</li>
<li>Добавьте библиотеку в ваш проект</li>
</ol>
<p style="text-align:justify;">Теперь приведу код интерфейса <code>IJSONSerializable</code> (объекта, который может быть свёрнут в <code>JSON</code> и развернут обратно — думаю, это довольно корректно) и абстрактного класса <code>JSONBean</code>, который его имплементирует.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>package com.acme.json;

import org.json.JSONObject;

public interface IJSONSerializable {

    public boolean fromJSONObj(JSONObject object);

    public JSONObject toJSONObject();

}</code></pre>
<p style="text-align:justify;">Обратите внимание, что в стандартной версии <code>JSON</code> по геттерам считает за пары ключ-свойство значения некоторых недозволенных методов, например, <code>getClass</code> и <code>getInstance</code> — нижеприведённый класс этот недостаток (в случае указанных методов) обходит и, собственно, добавляет функциональность конструирования (а в данном случае правильнее — инициализации) <code>Bean</code>&#8216;а из <code>JSON</code>-объекта. Да, здесь, иcпользуется <code>reflection</code>, и если вас не устраивает этот факт — вы вольны поменять концепцию :) — <code>JSON</code> выстраивает свой объект из <code>Bean</code>&#8216;а точно таким же способом.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>package com.acme.json;

import java.lang.reflect.Method;

import org.json.JSONException;
import org.json.JSONObject;

public abstract class JSONBean implements IJSONSerializable {

    public boolean fromJSONObj(JSONObject jsonObj) {
        Class beanClass = this.getClass();
        Method[] methods = beanClass.getMethods();
        for (int i = 0;  i &lt; methods.length; i += 1) {
            try {
                Method method = methods[i];
                String name = method.getName();
                String key = "";
                if (name.startsWith("set")) {
                    key = name.substring(3);
                }
                if (key.length() &gt; 0 &amp;&amp;
                        Character.isUpperCase(key.charAt(0)) &amp;&amp;
                        method.getParameterTypes().length == 1) {
                    if (key.length() == 1) {
                        key = key.toLowerCase();
                    } else if (!Character.isUpperCase(key.charAt(1))) {
                        key = key.substring(0, 1).toLowerCase() +
                            key.substring(1);
                    }
                    if (isAllowedKey(key))
                        method.invoke(this, jsonObj.get(key));
                }
            } catch (Exception e) {
                return false;
            }
        }
        return true;
    }

    public JSONObject toJSONObject() {
        return new JSONObject(this) {
            @Override
            public Object get(String key) throws JSONException {
                return isAllowedKey(key) ? super.get(key) : null;
            }
        };
    }

    protected static boolean isAllowedKey(String key) {
        return ((key != "class") &amp;&amp; (key != "instance"));
    }

}</code></pre>
<p style="text-align:justify;">Ну, и простенький пример <code>Bean</code>&#8216;а, с которым мы будем работать.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>package com.acme.json.beans;

import com.acme.json.JSONBean;

public class PersonBean extends JSONBean {

    private String personFirstName = "Homer";
    private String personLastName = "Simpson";
    private int personAge = 46;

    public String getPersonFirstName() {
        return personFirstName;
    }

    public void setPersonFirstName(String personFirstName) {
        this.personFirstName = personFirstName;
    }

    public String getPersonLastName() {
        return personLastName;
    }

    public void setPersonLastName(String personLastName) {
        this.personLastName = personLastName;
    }

    public int getPersonAge() {
        return personAge;
    }

    public void setPersonAge(int personAge) {
        this.personAge = personAge;
    }

}</code></pre>
<p style="text-align:justify;"><code>JSONBeanManager</code> управляет подготовкой <code>Bean</code>&#8216;ов для отправки и принятия их на основе параметров запроса. Думаю, концентрация этого кода в одном месте оправдана, поскольку вы вряд ли захотите, чтобы отвечающий за пересылку <code>Bean</code>&#8216;ов код был разбросан по проекту. В худших случаях паттерны проектирования придут вам на помощь. Кстати, возможно вы захотите сделать некоторые ваши <code>Bean</code>&#8216;ы <code>Singleton</code>&#8216;ами, тогда здесь вы можете возвращать их единственные инстансы (не забудьте только, что в связи с этим их нужно аккуратнее готовить :) ).</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>package com.acme.json;

import java.util.Map;

import com.acme.json.beans.PersonBean;

public class JSONBeanManager {

    protected JSONBean prepareBeanForReceiving(Map parametersMap) {
        if (parametersMap.containsKey("source") &amp;&amp;
           (parametersMap.get("source") == "sampleBean")) {
            return new PersonBean();
        }
        return null;
    }

    protected JSONBean prepareBeanForSending(Map parametersMap) {
        if (parametersMap.containsKey("source") &amp;&amp;
           (parametersMap.get("source") == "sampleBean")) {
            return new PersonBean();
        }
        return null;
    }

    protected void onBeanReceived(JSONBean bean) { }

    protected void onBeanSent(JSONBean bean) { }

    protected void onBeanTransferError() { }	

}</code></pre>
<p style="text-align:justify;">Ну и наконец — сервлет. Ядро пересылки. Запрос <code>GET</code> на сервер отправляет клиенту <code>Bean</code>, отданный менеджером на основе анализа параметров запроса, а затем сконвертированный в <code>JSON</code>-объект, а <code>POST</code> — принимает и заполняет предоставленный тем же менеджером <code>Bean</code> полученными из <code>JSON</code>-объекта данными.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>package com.acme.json;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONException;
import org.json.JSONObject;

public class JSONBeanServlet extends HttpServlet {

    protected static final String JSON_OBJ_PARAM = "jsonBean";

    private JSONBeanManager beanManager = null;

    public JSONBeanServlet(/*Class beanManagerClass*/) {
        super();
        this.beanManager = new JSONBeanManager();
    }

    @Override
    public void doGet(HttpServletRequest req,
            HttpServletResponse resp)
            throws java.io.IOException, ServletException {
        JSONBean activeBean =
            beanManager.prepareBeanForSending(req.getParameterMap());
        if (activeBean != null) {
            resp.setContentType("application/x-json");
            resp.getWriter().print(activeBean.toJSONObject());
            beanManager.onBeanSent(activeBean);
        } else {
            beanManager.onBeanTransferError();
            // throw new ServletException("JSONBeanServlet got
                    no bean for sending");
        }
    }	

    @Override
    protected void doPost(HttpServletRequest req,
            HttpServletResponse resp)
            throws ServletException, IOException {

        JSONBean activeBean =
            beanManager.prepareBeanForReceiving(req.getParameterMap());		

        if (activeBean != null) {
            String jsonText = req.getParameter(JSON_OBJ_PARAM);
            JSONObject jsonObj = null;
            try {
                jsonObj = new JSONObject(jsonText);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            activeBean.fromJSONObj(jsonObj);

            beanManager.onBeanReceived(activeBean);

        } else {
            beanManager.onBeanTransferError();
            // throw new ServletException("JSONBeanServlet got
                    no bean for receiving");
        }

    }	

}</code></pre>
<p style="text-align:justify;">Для завершения описания серверной части следует напомнить о добавлении сервлета в <code>web.xml</code>.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4"&gt;

    &lt;display-name&gt;SomeAplication&lt;/display-name&gt;

    . . .

    &lt;servlet&gt;
        &lt;description&gt;JSON Beans Manage Servlet&lt;/description&gt;
        &lt;display-name&gt;JSON Beans Servlet&lt;/display-name&gt;
        &lt;servlet-name&gt;JSON Beans Servlet&lt;/servlet-name&gt;
        &lt;servlet-class&gt;
            com.acme.json.FNJSONBeanServlet
        &lt;/servlet-class&gt;
    &lt;/servlet&gt;

    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;JSON Beans Servlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/jsonBean/*&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;

    . . .

&lt;/web-app&gt;</code></pre>
<p style="text-align:justify;">Клиентская часть состоит, собственно из <a href="http://www.json.org/json2.js"><code>JSON</code>-парсера-конструктора</a> (да, всё это можно сделать через <code>eval()</code>, но предоставленный разработчиками код делает это, по их обещаниям, аккуратнее) и, в моём случае, класса, облегчающего работу с сервлетом. Класс использует немного модифицированную функцию <code>makeRequest</code> из <a href="http://shamansir.wordpress.com/2007/08/12/16-%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be-%d0%bf%d0%be%d0%bb%d0%b5%d0%b7%d0%bd%d1%8b%d1%85-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b9-%d0%b4%d0%bb%d1%8f-javascr/">статьи о решениях <code>JavaScript</code></a> (которую я обновлю до этой версии там сразу же после написания статьи) и обеспечивающие ООП функции <code>Class</code> и <code>createMethodReference</code> оттуда же.</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>var JSONManager = Class.extend({

    JSON_BEAN_SERVLET_PATH: "./jsonBean",
    JSON_BEAN_PARAM_NAME: "jsonBean",

    construct:
        function() {
            this._handlerFuncRef =
                createMethodReference(this, "_responseHandler");
        },

    requestJSONBean: function(handlerFunc, addParams) {
        makeRequest(this.JSON_BEAN_SERVLET_PATH, addParams,
                this._handlerFuncRef, handlerFunc);
    },

    sendJSONBean: function(jsonBean, addParams) {
        makeRequest(this.JSON_BEAN_SERVLET_PATH,
                this.JSON_BEAN_PARAM_NAME + "=" +
                JSON.stringify(jsonBean) + (addParams ?
                ("&amp;" + addParams) : ""), null, true);
    },		

    _responseHandler: function(http_request, handlerFunc) {
        handlerFunc(JSON.parse(http_request.responseText));
    }

});</code></pre>
<p style="text-align:justify;">Ну и в завершение — пример использующего всё вышеприведённое кода:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>var alexanderJSON =
    {"personFirstName":    "Alexander",
     "personLastName":     "Makedonsky",
     "personAge":             35,
    };	

var jsonManager = new JSONManager();
jsonManager.sendJSONBean(alexanderJSON, "source=SampleBean");

var homerJSON = null;
function onGotObject(http_request) {
    homerJSON = JSON.parse(http_request.responseText);
}
jsonManager.requestJSONBean(onGotObject, "source=SampleBean");</code></pre>
<p style="text-align:justify;">В качестве альтернативных идей &#8211; методы <code>JSONBeanManager</code>&#8216;а можно сделать статическими, а <code>JSONBean</code> научить приготавливать самого себя к отправке (инициировать данными) &#8211; но при сложной структуре менеджера и требовании комплексной подготовки, когда <code>Bean</code> не может подготовить сам себя &#8211; придётся от них отказаться. Однако, поскольку выбор <code>Bean</code>&#8216;а по параметрам будет общим и для передачи и для приёма — код выбора можно вынести и в отдельный метод.</p>
<h5>Заключение</h5>
<p style="text-align:justify;">Кажется, задача ознакомления выполнена и я со спокойной совестью, надеюсь, могу идти делать другие дела (я помню про обновление функции :) ). Если совесть должна быть неспокойна &#8211; обязательно сообщайте, я стараюсь исправлять ошибки в своих статьях &#8211; и даже те, которые, изредка, сам нахожу со временем. Приятной вам разработки.</p>
<p><a href="http://shamansir.files.wordpress.com/2007/12/json.png" title="JSON-Java Class Diagram"><img src="http://shamansir.files.wordpress.com/2007/12/json.thumbnail.png?w=575" alt="JSON-Java Class Diagram" /></a><br />
<a href="http://shamansir.files.wordpress.com/2007/12/json-act.png" title="JSON-Java Sequence Diagram"><img src="http://shamansir.files.wordpress.com/2007/12/json-act.thumbnail.png?w=575" alt="JSON-Java Sequence Diagram" /></a></p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shamansir.wordpress.com/55/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shamansir.wordpress.com/55/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/55/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=55&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2007/12/11/java-json-ways-to-the-friendship/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/05/wikidot.gif" medium="image">
			<media:title type="html">This acrticle at wikidot.com</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/08/java.png" medium="image">
			<media:title type="html">J2EE</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/12/wordpress-json.png" medium="image">
			<media:title type="html">JSON</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/12/json.thumbnail.png" medium="image">
			<media:title type="html">JSON-Java Class Diagram</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/12/json-act.thumbnail.png" medium="image">
			<media:title type="html">JSON-Java Sequence Diagram</media:title>
		</media:content>
	</item>
		<item>
		<title>Редеплойинг приложения на Tomcat средствами Ant</title>
		<link>http://shamansir.wordpress.com/2007/09/15/application-redeployment-with-ant/</link>
		<comments>http://shamansir.wordpress.com/2007/09/15/application-redeployment-with-ant/#comments</comments>
		<pubDate>Sat, 15 Sep 2007 08:38:27 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[j2ee]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/2007/09/15/%d0%a0%d0%b5%d0%b4%d0%b5%d0%bf%d0%bb%d0%be%d0%b9%d0%b8%d0%bd%d0%b3-%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bd%d0%b0-tomcat-%d1%81%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b2%d0%b0/</guid>
		<description><![CDATA[Процесс разработки нашего проекта обладает одним минусом, свойственным многим J2EE-проектам: при изменении кода проекта и пересборке его сервер не сразу подхватывает обновку, а требует полного останова себя, очистки кэша, запуска себя по-новой и передеплойинга пакета. Для того чтобы не делать это каждый раз ручками есть несколько простых способов: например, те же скрипты (batch&#8217;и для windows [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=52&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a title="This acrticle at wikidot.com" href="http://shaman-sir.wikidot.com/ant-tomcat-redeploying"><img style="float:right;border:none;" src="http://shamansir.files.wordpress.com/2008/05/wikidot.gif?w=16&#038;h=16" alt="This acrticle at wikidot.com" width="16" height="16" /></a></p>
<p><a href="http://java.sun.com/javaee" title="J2EE"><img src="http://shamansir.files.wordpress.com/2007/08/java.png?w=575" alt="J2EE" style="border:1px dotted #000000;" /></a> <a href="http://tomcat.apache.org/" title="Apache Tomcat"><img src="http://shamansir.files.wordpress.com/2007/09/tomcat.png?w=575" alt="Apache Tomcat" style="border:1px dotted #000000;" /></a> <a href="http://ant.apache.org/" title="Apache Ant"><img src="http://shamansir.files.wordpress.com/2007/09/ant.png?w=575" alt="Apache Ant" style="border:1px dotted #000000;" /></a></p>
<p style="text-align:justify;">Процесс разработки нашего проекта обладает одним минусом, свойственным многим J2EE-проектам: при изменении кода проекта и пересборке его сервер не сразу подхватывает обновку, а требует полного останова себя, очистки кэша, запуска себя по-новой и передеплойинга пакета.</p>
<p style="text-align:justify;">Для того чтобы не делать это каждый раз ручками есть несколько простых способов: например, те же скрипты (batch&#8217;и для windows и shell-скрипты для linux). Но мне показалось более простым сделать так,  чтобы делал это сам собирающий ant-скрипт (сценарий?): одно нажатие клавиши и все просходит автоматически&#8230;</p>
<p><span id="more-52"></span> (версия для windows)</p>
<p style="text-align:justify;">Поэтому я взял скрипт существующий и стал его править. Пришлось столкнуться с несколькими проблемами/хитростями ant&#8217;а на windows (опытному в ant&#8217;о-строении человеку они конечно нипочем :) ), в результате чего получился рабочий скрипт, выдержки из которого я и разберу ниже.</p>
<p style="text-align:justify;">Вот &#8211; файл <code>build.properties</code>. Он содержит некоторые значения, которые возможно будут часто меняться и поэтому лучше хранить их отдельно от ant-срипта.</p>
<pre><code># имя пакета
war.name = SomeProjectPackage

# путь к JDK
java.home = "C:WorktableJavajdk1.5.0_12"
# путь к корневому каталогу сервера
server.dir = C:/Worktable/Java/apache-tomcat-5.5.25
# скрипт, использующийся для запуска сервера
server.command = catalina.bat

# путь к расположению проекта
root.dir = C:/Workspace/SomeProject
# путь к месту, куда на сервере будет выкладываться пакет
deploy.dir = ${server.dir}/webapps/

# настройки JPDA (удаленнный дебаггинг может осуществляться
# (например, средствами Eclipse) подключением к указанному порту)
jpda.transport = dt_socket
jpda.port = 56666

# путь к библиотекам проекта
lib.dir = ${root.dir}/lib/
# путь к временному месту сборки проекта
dist.dir = ${root.dir}/dist/
# путь к каталогу с веб-содержимым - страницами, скриптами и т.п.
web.dir = ${root.dir}/WebContent/</code></pre>
<p style="text-align:justify;">Теперь по частям рассмотрим сам скрипт. В заголовке &#8211; включаем наш файл <code>.properties</code>.</p>
<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;

    &lt;project name="SomeProject" default="redeploy" basedir="."&gt;
    &lt;property file="build.properties"/&gt;

    . . .</code></pre>
<p style="text-align:justify;">Далее идут цели сборки (<code>build</code>), очистки временных каталогов, использованных при сборке (<code>clean</code>) и цель пересборки &#8211; очищающая, а затем собирающая (<code>rebuild</code>). Их подробное рассмотрение не относится к цели статьи :).</p>
<pre><code>    . . .

    &lt;!-- Compiles project with all dependencies. --&gt;

    &lt;target name="build"
            description="--&gt; compiles project with all dependencies"&gt;
        &lt;mkdir dir="${dist.dir}"/&gt;
        &lt;mkdir dir="${dist.dir}/classes"/&gt;
        &lt;javac source="1.5"
            srcdir="${root.dir}/src"
            destdir="${dist.dir}/classes"
            debug="on"
            verbose="false"
            optimize="on"&gt;
            &lt;classpath&gt;
                &lt;fileset dir="${lib.dir}" includes="**/*.jar"/&gt;
            &lt;/classpath&gt;
        &lt;/javac&gt;
    &lt;/target&gt;

    &lt;!-- Cleans the build. --&gt;

    &lt;target name="clean"
            description="--&gt; cleans the build"&gt;
        &lt;delete quiet="true" dir="${dist.dir}"/&gt;
    &lt;/target&gt;

    &lt;!-- Rebuild. --&gt;

    &lt;target name="rebuild" depends="clean,build"
            description="--&gt; [clean, build]"/&gt;

    . . .</code></pre>
<p style="text-align:justify;">А вот, собственно, наши подчиненные &#8211; цели деплойинга (выкладывания нового пакета на сервер), де-деплойинга (забирания старого пакета с сервера) и пере-деплойинга (забирания старого, а потом выкладывания нового).</p>
<p style="text-align:justify;">При выкладывании (<code>deploy</code>) мы компилируем код (<code>depends="build"</code>), затем создаем на сервере каталог для логов, собираем пакет из скомпилированных исходников (командой <code>jar</code>), выкладывая его во временный каталог, а затем запускаем сервер. Для Windows сервер из ant-скрипта может быть запущен только в своем окружении, для этого приходится вызывать его командой <code>cmd /c catalina.bat jpda start</code>, через команду ant&#8217;а <code>exec</code> (аргументы должны быть разделены командами <code>arg</code> именно так, как представлено ниже &#8211; для того чтобы <code>exec</code> обернул команду <code>catalina jpda start</code> в кавычки, для ее целостности). Также серверу нужно передать несколько переменных окружения, что мы и делаем, используя команды <code>env</code>. Сервер мы запускаем в отдельном потоке (<code>spawn="true"</code> &#8211; иначе скрипт будет ожидать от сервера команды завершения и не будет производить дальнейших действий) и в чистом виде (не через ява-машину &#8211; <code>vmlauncher="false"</code>). Сервер запущен, можно выложить туда пакет и удалить временные каталоги и файлы (последовательность команд <code>copy</code> и двух <code>delete</code>).</p>
<p style="text-align:justify;">Для выгрузки пакета с сервера (<code>undeploy</code>) мы останавливаем серевер по правилам, описанным выше (при остановке мы можем не указывать переменные окружения для JPDA и подолждать пока сервер остановится; но если что-то не вышло &#8211; это нормально &#8211; возможно сервер и не был запущен (<code>failifexecutionfails="false"</code>)). Затем мы очищаем каталог на сервере, в которые он распаковывал наш пакет, удаляем сам пакет и очищаем кэш сервера.</p>
<p style="text-align:justify;">При перевыладке (<code>redeploy</code>) &#8211; цели по умолчанию &#8211; старая версия пакета удаляется с сервера (<code>undeploy</code>), очищаются временные каталоги (clean), и пакет собирается и выкладывается на сервер (<code>deploy</code>).</p>
<pre><code>    . . .

    &lt;!-- Prepares deployment --&gt;

    &lt;target name="pre-deploy"&gt;
        &lt;mkdir dir="${dist.dir}/war"/&gt;
        &lt;mkdir dir="${dist.dir}/war/WEB-INF"/&gt;
        &lt;mkdir dir="${dist.dir}/war/WEB-INF/classes"/&gt;
        &lt;mkdir dir="${dist.dir}/war/WEB-INF/lib"/&gt;
        &lt;copy todir="${dist.dir}/war"&gt;
            &lt;fileset dir="${web.dir}"&gt;
                &lt;include name="**/*.*"/&gt;
            &lt;/fileset&gt;
        &lt;/copy&gt;
        &lt;copy todir="${dist.dir}/war/WEB-INF/classes"&gt;
            &lt;fileset dir="${dist.dir}/classes"&gt;
                &lt;include name="**/*.*"/&gt;
            &lt;/fileset&gt;
        &lt;/copy&gt;
        &lt;copy todir="${dist.dir}/war/WEB-INF/lib" flatten="true"&gt;
            &lt;fileset dir="${lib.dir}"&gt;
                &lt;include name="**/*.jar"/&gt;
            &lt;/fileset&gt;
        &lt;/copy&gt;
    &lt;/target&gt;

    &lt;!-- Deploys application on server. --&gt;

    &lt;target name="deploy" depends="rebuild, pre-deploy"
            description="--&gt; deploys application on server"&gt;
        &lt;mkdir dir="${server.dir}/logs"/&gt;
        &lt;jar jarfile="${war.name}.war" basedir="${dist.dir}/war"/&gt;
        &lt;exec dir="${server.dir}/bin" executable="cmd"
                vmlauncher="false" spawn="true"&gt;
            &lt;env key="JAVA_HOME" value="${java.home}"/&gt;
            &lt;env key="JPDA_TRANSPORT" value="${jpda.transport}" /&gt;
            &lt;env key="JPDA_ADDRESS" value="${jpda.port}" /&gt;
            &lt;env key="CATALINA_HOME" value="${server.dir}"/&gt;
            &lt;arg value="/c" /&gt;
            &lt;arg value="${server.command} jpda start"/&gt;
        &lt;/exec&gt;

        &lt;copy file="${war.name}.war" todir="${deploy.dir}"/&gt;
        &lt;delete dir="${dist.dir}" failonerror="false" /&gt;
        &lt;delete file="${war.name}.war" failonerror="false" /&gt;
    &lt;/target&gt;

    &lt;!-- Un-deploys application from server. --&gt;

    &lt;target name="undeploy"
            description="--&gt; un-deploys application from server"&gt;
        &lt;exec dir="${server.dir}/bin" executable="cmd"
                failifexecutionfails="false" vmlauncher="false"&gt;
            &lt;env key="JAVA_HOME" value="${java.home}"/&gt;
            &lt;env key="CATALINA_HOME" value="${server.dir}"/&gt;
            &lt;arg value="/c" /&gt;
            &lt;arg value="${server.command} stop"/&gt;
        &lt;/exec&gt;

        &lt;delete quiet="true"&gt;
            &lt;fileset dir="${deploy.dir}"&gt;
                &lt;include name="${war.name}*"/&gt;
            &lt;/fileset&gt;
        &lt;/delete&gt;

        &lt;delete dir="${deploy.dir}/${war.name}" failonerror="false"/&gt;
        &lt;delete file="${deploy.dir}/${war.name}.war" failonerror="false" /&gt;
        &lt;delete dir="${server.dir}/work/Catalina" failonerror="false" /&gt;
    &lt;/target&gt;

    &lt;!-- Re-deploys application on server. --&gt;

    &lt;target name="redeploy"
            depends="undeploy,clean,deploy"
            description="--&gt; [undeploy,clean,deploy]"&gt;
    &lt;/target&gt;

    &lt;/project&gt;

&lt;/xml&gt;</code></pre>
<p style="text-align:justify;">Собственно, все :)</p>
<p style="text-align:justify;">P.S. Теперь основные мои статьи будут уходить, видимо, на <a href="http://realcoding.net">realcoding.net</a>. И, скорее всего, это будут циклы статей. Здесь, конечно же, я буду извещать вас о появлении их там.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shamansir.wordpress.com/52/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shamansir.wordpress.com/52/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/52/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=52&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2007/09/15/application-redeployment-with-ant/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/05/wikidot.gif" medium="image">
			<media:title type="html">This acrticle at wikidot.com</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/08/java.png" medium="image">
			<media:title type="html">J2EE</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/09/tomcat.png" medium="image">
			<media:title type="html">Apache Tomcat</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/09/ant.png" medium="image">
			<media:title type="html">Apache Ant</media:title>
		</media:content>
	</item>
		<item>
		<title>ООП и JavaScript</title>
		<link>http://shamansir.wordpress.com/2007/08/19/oop-and-javascript/</link>
		<comments>http://shamansir.wordpress.com/2007/08/19/oop-and-javascript/#comments</comments>
		<pubDate>Sat, 18 Aug 2007 22:29:55 +0000</pubDate>
		<dc:creator>shaman.sir</dc:creator>
				<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://shamansir.wordpress.com/2007/08/19/%d0%9e%d0%9e%d0%9f-%d0%b8-javascript/</guid>
		<description><![CDATA[В предыдущей статье я представил на ваше рассмотрение небольшой кусок кода, который позволяет использовать три столпа ООП в JavaScript. Все это достигается довольно хитро и я, честно признаюсь, пока не слишком хорошо знаю, как это работает (остальное &#8211; конечно &#8211; знаю :) ) &#8211; в комментах меня вывели на чистую воду :). Тем не менее [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=50&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a title="This acrticle at wikidot.com" href="http://shaman-sir.wikidot.com/javascript-oop"><img style="float:right;border:none;" src="http://shamansir.files.wordpress.com/2008/05/wikidot.gif?w=16&#038;h=16" alt="This acrticle at wikidot.com" width="16" height="16" /></a></p>
<p><a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm" title="JavaScript"><img src="http://shamansir.files.wordpress.com/2007/08/javascript.png?w=575" alt="JavaScript" style="border:1px dotted #000000;" /></a></p>
<p style="text-align:justify;">В <a href="http://shamansir.wordpress.com/2007/08/12/16-%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be-%d0%bf%d0%be%d0%bb%d0%b5%d0%b7%d0%bd%d1%8b%d1%85-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b9-%d0%b4%d0%bb%d1%8f-javascr/">предыдущей статье</a> я представил на ваше рассмотрение небольшой кусок кода, который позволяет использовать три столпа ООП в JavaScript. Все это достигается довольно хитро и я, честно признаюсь, пока не слишком хорошо знаю, как это работает (остальное &#8211; конечно &#8211; знаю :) ) &#8211; в комментах меня вывели на чистую воду :). Тем не менее я позволил себе чуточку изменить функцию <code>extend</code>, дабы классы имели понятие о том, что такое статические константы (на самом деле константы конечно получились условные, но это думаю можно оправдать условностью их в самом JavaScript). Здесь я рассмотрю этот вопрос поподробнее и, видимо, буду расширять статью по мере его более глубокого понимания.</p>
<p><span id="more-50"></span></p>
<p style="text-align:justify;">Итак, исходные данные (повторюсь, заимствованы из источников на <a href="http://www.ajaxpath.com/javascript-inheritance" title="JavaScript Inheritance on AJAXPath">AJAXPath</a> и на <a href="http://ajaxpatterns.org/Javascript_Inheritance" title="JavaScript Inheritance on AJAXPatterns">AJAXPatterns</a>):</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>function Class() { };

Class.prototype.construct = function() { };

Class.extend = function(def) {

    var classDef = function() {
        if (arguments[0] !== Class) {
            this.construct.apply(this, arguments);
        }
    };

    var proto = new this(Class);
    var superClass = this.prototype;

    for (var n in def) {
        var item = def[n];
        if (item instanceof Function) item.$ = superClass;
                else classDef[n] = item;
        proto[n] = item;
    }

    classDef.prototype = proto;
    classDef.extend = this.extend;

    return classDef;
};</code></pre>
<p style="text-align:justify;">Благодаря использованию трех этих функций, у вас появляется замечательная возможность строить довольно серьезные и обширные по конструкции фреймворки, не теряя при этом читабельности кода и возможности быстро найти нужное место дабы его изменить. Ну и плюс, конечно, практически все преимущества ООП.</p>
<p style="text-align:justify;">Эти три функции использовались как фундамент ООП-Drag&#8217;n'Drop фреймворка для крупного проекта на Java+Wicket. Я бы с удовольствием безвозмездно поделился бы его кодом, но по контракту этот код &#8211; собственность компании, а компания не хочет его рассекречивать. По этой причине я могу лишь дать, если нужно, наводящие мысли, наводящие на конкретные мысли :).</p>
<p style="text-align:justify;">Впрочем, ближе к делу. Для такого кода требуется пример. Я наваял тут небольшой скрипт, эмулирующий операционную систему Windows, надеюсь он подойдет:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>/* пара вспомогательных функций */

function getInstanceOf(className) {
    // возвращает объект класса по имени класса
    return eval('new ' + className + '()');
}

function pause(millis) // останавливает выполнение
    // скрипта на указанное количество миллисекунд
{
    var time = new Date();
    var curTime = null;
    do { curTime = new Date(); }
        while( curTime - time &lt; millis);
}

/* === Абстрактная Операционная Система === */

var AbstractOS = Class.extend({

    construct: // конструктор, параметр - тип компьютера
        function(computerClassName) {
            // компьютер, на котором запускается ОС
            this._computer = getInstanceOf(computerClassName);
        },

    getComputer: function() { return this._computer; },

    reboot: // перезагрузка ОС
        function() {
            return this.getComputer().shutDown() &amp;&amp;
                     this.getComputer().startUp();
        },

    shutDown: // выключение ОС
        function() { return this.getComputer().shutDown(); },

    startUp: // запуск ОС
        function() { return this.getComputer().startUp(); },

    exec: // абстрактный (условно) метод запуска команды
        function(commandStr) { return false; },

    cycle: // запуск ОС, выполнение команды, отключение ОС
        function(cmdStr) {
            return this.startUp() &amp;&amp; this.exec(cmdStr) &amp;&amp;
                                    this.shutDown();
        }

});

/* === Синий Экран Смерти === */

var BSOD = Class.extend({

    launch: // запуск
        function() {
            alert('You see the BSOD');
            return true;
        }

});

/* === Операционная Система MS Windows === */

var MSWindows = AbstractOS.extend({
    // наследуется от абстрактной ОС

    // сообщения - статические константы (условно)
    STARTUP_MSG: 'Windows Starting',
    EXEC_MSG: 'This program has performed an illegal operation',
    REBOOT_MSG: 'Do you really want to reboot your computer?',

    construct: // конструктор, параметр - тип компьютера
        function(computerClassName) {
            // вызов родительского конструктора
            arguments.callee.$.construct.call(this, computerClassName);
            // кэш-е синего экрана смерти (ибо он будет один)
            this._bsod = new BSOD();
        },

    getBSOD: function() { return this._bsod; },

    reboot: // перегруженная перезагрузка
        function() {
            // вывод сообщения
            alert(MSWindows.REBOOT_MSG);
            // вызов родительского метода
            return arguments.callee.$.reboot.call(this);
        },

    shutDown: // перегруженное выключение
        function() {
            // запуск СЭС и, если он удачен - вызов
            // родительского метода. возвращается результат
            // удачности
            return (this.getBSOD().launch() &amp;&amp;
                arguments.callee.$.shutDown.call(this));
        },

    startUp: //  перегруженная загрузка
        function() {
            // если удачно выполнился родительский метод
            if (arguments.callee.$.startUp.call(this)) {
                // выполнить необходимые операции
                pause(400);
                //setTimeout("alert('Windows Starting')", 400);
                // сообщить об удачной загрузке
                alert(MSWindows.STARTUP_MSG);
                return true;
            } else return false; // нет - так нет
        },

    exec: // перегруженное выполнение команды
        function(commandStr) {
            // если команда валидна - выдать результат
            // исполнения, иначе - выключиться
            return commandStr
                ? alert(MSWindows.EXEC_MSG)
                : this.shutDown();
        }

});

/* === Обычный Компьтер === */

var SimpleComputer = Class.extend({

    startUp: // при запуске выводит сообщение
        function() { alert('Starting Up'); return true; },

    shutDown: // при выключении выводит сообщение
        function() { alert('Shutting Down'); return true; }

});

/* проверочная функция */

function perform() {
    // инициируем ОС на обычном компьютере (инсталляция)
    var testOs = new MSWindows('SimpleComputer');
    // запускаем ОС
    testOs.startUp();
    // выполняем банальную команду
    testOs.exec('ls -laF');
    // выключаем ОС
    testOs.shutDown();
}</code></pre>
<p style="text-align:justify;"><strong>NB!</strong> (не забывайте &#8211; после последнего объявления метода в классе запятой ставить не нужно, иначе Ослик (IE) обидится)</p>
<p style="text-align:justify;">Если предыдущий пример вам не понравился &#8211; я могу предложить вам довольно полезный класс, который сильно помогает, если в вашем проекте понятие элемента DOM пересекается с понятием объекта, над которым производятся манипуляции:</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>var ElementWrapper = Class.extend({

    construct:
        function(elementId) {
            this.elementId = elementId;
            this.element = null;
            this._initializeElement();
        },

    _initializeElement:
        function() {
            var docElm = document.getElementById(this.elementId);
            if (!docElm) {
                this.element = document.createElement('div');
                this.element.id = this.elementId;
            } else {
                this.element = docElm;
            }
            this._assignListeners();
        },

    _assignListeners:
        function() {
            . . .
        },

    . . .

    reassignTo:
        function(elementId) {
            this.elementId = elementId;
            this.element = null;
            this._initializeElement();
        }

});</code></pre>
<p style="text-align:justify;">От этого класса очень удобно наследовать классы, расширяющие функциональность элементов DOM. Также, теперь вы можете использовать код типа этого:</p>
<pre style="border:1px dotted #999999;background-color:#dddddd;padding:5px;"><code>var someElement = new ElementWrapper('someElmId');</code></pre>
<p style="text-align:justify;">&#8230;и объект <code>someElement</code> будет связан с элементом (оборачивать элемент) с <code>id</code> <em>&#8216;SomeElmId&#8217;</em>. Доступ к нему &#8211; как к элементу DOM &#8211; можно будет получить через свойство <code>someElement.element</code>.</p>
<p style="text-align:justify;">Приведенный ниже класс наследуется от <code>ElementWrapper</code> и позволяет обращаться с обернутым элементом как с практически полноценным (неполноценным? :) ) графическим объектом (используются некоторые функции из <a href="http://shamansir.wordpress.com/2007/08/12/16-%d0%b4%d0%b5%d0%b9%d1%81%d1%82%d0%b2%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be-%d0%bf%d0%be%d0%bb%d0%b5%d0%b7%d0%bd%d1%8b%d1%85-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b9-%d0%b4%d0%bb%d1%8f-javascr/">предыдущей статьи</a>: <code>getElmAttr</code>, <code>setElmAttr</code>, <code>findOffsetHeight</code>, <code>getPosition</code>, <code>getAlignedPosition</code>):</p>
<pre style="border:1px dotted #999999;background-color:#eeeeee;padding:5px;"><code>var DEF_NS = 'def';

var DEF_LWIDTH_ATTR 	= 'localWidth';
var DEF_LHEIGHT_ATTR 	= 'localHeight';
var DEF_LTOP_ATTR 		= 'localTop';
var DEF_LLEFT_ATTR 		= 'localLeft';

var GraphicalElementWrapper = ElementWrapper.extend({

    _assignListeners:
        function() {
            // do not assign listeners if not required
        },

    setLocalWidth:
        function(localWidth) {
            setElmAttr(this.element, DEF_LWIDTH_ATTR,
                        localWidth + 'px', DEF_NS);
        },

    setLocalHeight:
        function(localHeight) {
            setElmAttr(this.element, DEF_LHEIGHT_ATTR,
                        localHeight + 'px', DEF_NS);
        },

    setLocalLeft:
        function(localLeft) {
            setElmAttr(this.element, DEF_LLEFT_ATTR,
                        localLeft + 'px', DEF_NS);
        },			

    setLocalTop:
        function(localTop) {
            setElmAttr(this.element, DEF_LTOP_ATTR,
                        localTop + 'px', DEF_NS);
        },	

    getLocalWidth:
        function() {
            return getElmAttr(this.element, DEF_LWIDTH_ATTR, DEF_NS);
        },

    getLocalHeight:
        function() {
            return getElmAttr(this.element, DEF_LHEIGHT_ATTR, DEF_NS);
        },		

    getLocalLeft:
        function() {
            return getElmAttr(this.element, DEF_LLEFT_ATTR, DEF_NS);
        },			

    getLocalTop:
        function() {
            return getElmAttr(this.element, DEF_LTOP_ATTR, DEF_NS);
        },

    getOffsetWidth:
        function() {
            return this.element.offsetWidth;
        },

    getOffsetHeight:
        function() {
            return this.element.offsetHeight ||
                     this.element.style.pixelHeight ||
                     findOffsetHeight(this.element);
        },

    show: // отобразить
        function() {
            this.element.style.display    = '';
            this.element.style.visibility = 'visible';
        },

    hide: // спрятать
        function() {
            if (this.element.style.display != 'none') {
                this.element.style.display  = 'none';
            }
        },

    blank: // "забелить"
        function() {
            if (this.element.style.display != '') {
                this.element.style.display    = '';
                this.element.style.visibility = 'hidden';
            }
        },

    makeBlock: // сделать блоком
        function() {
            if (this.element.style.display != 'block') {
                this.element.style.display  = 'block';
            }
        },			

    isPointInside: // опередляет принадлежность точки элементу
        function(curPoint) {
            return (parseInt(this.getLocalLeft()) &lt; curPoint.x) &amp;&amp;
                   (parseInt(this.getLocalTop()) 0 ?
                    parseInt(this.getLocalLeft()) : 0) +
                   parseInt(this.getLocalWidth()))  &gt; curPoint.x) &amp;&amp;
                   (((parseInt(this.getLocalTop())  &gt; 0 ?
                      parseInt(this.getLocalTop())  : 0) +
                     parseInt(this.getLocalHeight())) &gt; curPoint.y);
        },

    isElementNear: // определяет, перекрывает ли другой эл-т
            // текущий своей большей частью
        function(graphicalElement) {
            if (graphicalElement) {
                var elmCurPos = getPosition(graphicalElement.element);
                var elmHalfHeight =
                        parseInt(graphicalElement.getLocalHeight())/2;
                var elmHalfWidth =
                        parseInt(graphicalElement.getLocalWidth())/2;
                var localLeft =
                        (parseInt(this.getLocalLeft()) &gt; 0 ?
                         parseInt(this.getLocalLeft()) : 0);
                var localTop =
                        (parseInt(this.getLocalTop()) &gt; 0 ?
                         parseInt(this.getLocalTop()) : 0);
                var leftCorrect =
                        (elmCurPos.x &gt; (localLeft - elmHalfWidth)) &amp;&amp;
                        (elmCurPos.x  (localTop - elmHalfHeight)) &amp;&amp;
                        (elmCurPos.y &lt; (localTop +
                            parseInt(this.getLocalHeight()) -
                            elmHalfHeight));
                return leftCorrect &amp;&amp; topCorrect;
            } else return false;
        },

    recalc: // пересчитывает координаты
        function() {
            var pos = getAlignedPosition(this.element);
            this.setLocalWidth(parseInt(this.getOffsetWidth()));
            this.setLocalHeight(parseInt(this.getOffsetHeight()));
            this.setLocalLeft(pos.x);
            this.setLocalTop(pos.y);
        }

});</code></pre>
<p style="text-align:justify;">Оба этих класса, надеюсь, помогут вам при решении задач, связанных с опознаванием элементов DOM как графических объектов (например, Drag&#8217;n'Drop (здесь я наследовал класс перетаскиваемыx нод, классы областей, их содержащих (несколько с разными свойствами, отнаследованных друг от друга) и помощник для перетаскивания &#8211; от <code>GraphicElementWrapper</code>, а главный контейнер &#8211; от <code>ElementWrapper</code>) или, например, веб-приложение, эмулирующее работу оконного (здесь, когда я этим занимался, я наследовал перетаскиваемые элементы от <code>GraphicElementWrapper</code>, а меню, статусбар, рабочую область &#8211; от <code>ElementWrapper</code>).</p>
<p style="text-align:justify;">Как всё это работает &#8211; оказывается, непростой вопрос, но я постараюсь через некоторое время уделить внимание и ему, в этой же статье&#8230; А пока &#8211; кажется всё. Удач в JS-конструировании :).</p>
<h3>Ссылки</h3>
<p>про это&#8230;</p>
<ul>
<li>&#8230; &#8211; <a href="http://dklab.ru/chicken/nablas/40.html">по-русски, от Дмитрия Котерова</a></li>
<li>&#8230; &#8211; <a href="http://forum.dklab.ru/comments/nablas/40InheritanceInJavascript.html?start=80&amp;sid=fac82f100376bdaceb0f5024b136fb0c">более поздние впечатления &#8211; по-русски, от Дмитрия Котерова и его соратников</a></li>
<li>&#8230;<a href="http://ajaxpatterns.org/Javascript_Inheritance">на AjaxPatterns</a></li>
<li>&#8230;<a href="http://www.ajaxpath.com/javascript-inheritance/">на AJAXPath</a></li>
<li>&#8230;<a href="http://www.xml.com/pub/a/2006/06/07/object-oriented-javascript.html">на XML.com</a></li>
<li>&#8230;<a href="http://www.webreference.com/js/column79/">на WebReference.com</a></li>
<li>&#8230;<a href="http://www.codeproject.com/aspnet/JsOOP1.asp">на The Code Project</a></li>
<li>&#8230;<a href="http://www.javascriptkit.com/javatutors/oopjs.shtml">на JavaScript Kit</a></li>
<li>&#8230;<a href="http://www.devarticles.com/c/a/JavaScript/ObjectOriented-JavaScript-An-Introduction-to-Core-Concepts/">на DevArticles</a></li>
<li>&#8230; &#8211; <a href="http://chunkysoup.net/advanced/oojavascript1/">как на этом делать галерею</a></li>
<li>&#8230;<a href="http://www.kevlindev.com/tutorials/javascript/inheritance/index.htm">кратко, от Kevin Lindsey</a></li>
<li>&#8230;<a href="http://blogs.nitobi.com/dave/?p=166">кратко, от Dave Johnson</a></li>
<li>&#8230; &#8211; <a href="http://forum.vingrad.ru/index.php?showtopic=120066&amp;view=findpost&amp;p=1215304">ссылки от Zeroglif</a></li>
</ul>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shamansir.wordpress.com/50/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shamansir.wordpress.com/50/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shamansir.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shamansir.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shamansir.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shamansir.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shamansir.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shamansir.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shamansir.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shamansir.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shamansir.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shamansir.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shamansir.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shamansir.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shamansir.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shamansir.wordpress.com/50/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=shamansir.wordpress.com&amp;blog=1450937&amp;post=50&amp;subd=shamansir&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://shamansir.wordpress.com/2007/08/19/oop-and-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4a2d33923a3370522905ebd5ab5f14cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaman.sir</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2008/05/wikidot.gif" medium="image">
			<media:title type="html">This acrticle at wikidot.com</media:title>
		</media:content>

		<media:content url="http://shamansir.files.wordpress.com/2007/08/javascript.png" medium="image">
			<media:title type="html">JavaScript</media:title>
		</media:content>
	</item>
	</channel>
</rss>
