Веб Дизайн - статьи

         

Ruptime


Команда ruptime используется для проверки статуса других машин в вашей локальной сети или в вашей локальной подсети, если ваша сеть разделена на подсети. Для использования ruptime введите

ruptime

Результат будет выведен на экран. Вывод команды ruptime сходен с выводом, получаемым в результате выполнения команды uptime , отличие состоит лишь в том, что для команды ruptime количество дней, в течение которых удаленная машина была включена, отделяется от количества часов знаком `` + ''. По выводу команды можно увидеть, как долго каждая система была включена, как много пользователей сделали login и какова загрузка удаленных машин.



Rwho


Если ваша сеть имеет широковещательные возможности, то вы можете использовать команду rwho для определения, кто из удаленных пользователей сделал login и на каких машинах вашей локальной сети или локальной подсети, если ваша система использует подсети. Для использования команды введите

rwho

На экран выведется результат выполнения команды. Если вы зададите опцию `` -а ", то получите более детальную информацию, а если задать опцию `` -r ", то можно получить список удаленных пользователей в обратном алфавитном порядке. Замечание: rwho команда работает только на тех машинах, где запущена специальная системная задача rwho daemon .



Сценарии и документы


Практическая часть этой статьи позволяет придти к выводу, что сами по себе органы управления ActiveX практически бесполезны без поддержки со стороны сценариев, встраиваемых в HTML-документ. Так что легко понять, почему Microsoft считает сценарии в Internet Explorer компонентом, не уступающим по важности самим органам управления. И хотя для профессиональных Web-дизайнеров, большинство из которых ориентировались до сих пор на Netscape Navigator, концепция сценариев не является чем-то особенно новым, в самой системе ActiveX сценарии занимают очень важное место.

Впрочем, кое-что новое для пользователей Netscape в сценариях Internet Explorer все-таки есть - это поддержка нового языка VBScript, особого "сценарного" диалекта Visual Basic ("Visual Basic Scripting Edition"). Вероятно, поддержка VBScript позволит привлечь к работе со сценариями много программистов-любителей, которые обычно хорошо знакомы с Visual Basic. Считается, что С-подобный синтаксис JavaScript отпугивает от этого языка многих начинающих программистов.

Двуязычие броузера Internet Explorer делает осмысленным и даже необходимым использование атрибута LANGUAGE тега <SCRIPT> для указания языка сценария. Кроме того, поддержка двух языков потребовала введения дополнительного необязательного аргумента в тех функциях, одним из аргументов которых является строка кода. Например, функция setTimeout (), имевшая в Netscape Navigator два аргумента, теперь может принимать третий аргумент, который сообщает этой функции, как интерпретировать строку кода в первом из аргументов - как программу на JavaScript или на VBScript.

Следует иметь в виду, что, хотя вариант языка JavaScript, используемый Internet Explorer, и называется "JScript" во всех официальных документах Microsoft, на синтаксисе языка это никак не отразилось - во всех местах, где требуется указать один из двух языков, допустимыми вариантами являются либо "JavaScript", либо "VBScript" (а кое-где только "JavaScript" - некоторые функции языку VBScript пока недоступны).




В целом JScript представляет собой довольно сильно облегченный вариант JavaScript - особенно если сравнивать его с тем JavaScript, который поддерживает Netscape Navigator 3.0. Многие методы, события, объекты отсутствуют напрочь, некоторые, похоже, копировались из Netscape Navigator в большой спешке (попробуйте, к примеру, вызвать метод navigator.appCodeName (), долженствующий возвращать "кодовое имя броузера"), и даже в синтаксис введены некоторые серьезные упрощения - в частности, числовые значения больше не являются объектами. Очевидно, немало сценариев для Netscape Navigator потребуют переделок, прежде чем их сможет выполнить Internet Explorer. К сожалению, на момент написания этой статьи Microsoft даже не подготовила еще официальной документации на свой вариант JavaScript; все, что мне удалось найти на сервере Microsoft, - это документ под заглавием "Microsoft Internet Explorer Scripting Object Model", содержащий перечисление поддерживаемых JScript объектов и их свойств и методов.

Что же такое "ActiveX Documents" - последняя часть трилогии ActiveX? Проще всего это можно объяснить так: "документы ActiveX" дают Интернету то, к чему для рядового пользователя Windows и сводится технология OLE - когда, например, в окне Microsoft Word вдруг появляется самая настоящая таблица Excel, с которой можно делать все то же самое, что и в самом Excel. Точно так же HTML-документ может теперь (кстати, с помощью все того же тега <OBJECT>) включать в себя документы любых других форматов, для которых существуют программы просмотра, удовлетворяющие стандартам OLE.

Так, чтобы пользователь мог, не выходя из своего броузера, познакомиться с содержимым документа в некотором формате X, должны выполняться два условия: во-первых, для этого формата должна существовать программа просмотра, способная выполнять роль OLE-сервера, и во-вторых, эта программа должна быть установлена на компьютере пользователя. Очевидно, что оба эти условия накладывают заметные ограничения на практическое использование этой идеи.




Несмотря даже на то, что для всех приложений, входящих в Microsoft Office, существуют бесплатно распространяемые программы просмотра (Word Viewer, Excel Viewer и т.п.), рассчитывать на их присутствие на каждом компьютере не может даже корпорация Microsoft, - не говоря уж о других, менее известных фирмах, форматах и программах. Понятно, что о такой роскоши, как перенос на другую операционную систему, здесь не стоит и заикаться.

С другой стороны, документы ActiveX буквально обречены на успех в закрытых от внешнего мира сетях крупных корпораций (так называемых интрасетях), большинство из которых уже перешли на использование технологий Интернета. Как правило, администраторам таких сетей не составляет большого труда контролировать аппаратные и программные средства своих пользователей. Теперь, чтобы довести до сведения всех сотрудников новый приказ начальства, секретарше даже не нужно будет конвертировать его в HTML - она вполне может положить на главный сервер своей корпорации файл прямо в формате Word!


Сервлеты на базе Apache


Для тех, кто имеет дело с различными компьютерными платформами и стремится к универсализму, выбор Apache HTTP-сервера является, пожалуй, самым подходящим. Разве плохо, когда написанные вами модули могут работать и на ПК и на многопроцессорных высокопроизводительных системах, причем инсталляция и компоновка рабочих программ, как правило не требуется, дело сводится к простому копированию. Можно, не выходя из офиса, перемещать рабочие программы в специальные каталоги Web-сервера, находящегося за тридеять земель, и они мгновенно могут быть востребованы десятками пользователей, которым нет необходимости загружать их на свои компьютеры. До недавнего времени все Web-серверы могли вызывать на выполнение только три типа процессов: CGI, ISAPI или NSAPI, причем два последних чаще всего были реализованы на Wintel-платформе. Так, с появлением Delphi-3 многие стали предлагать свои разработки в виде Web-модулей, но аппетиты пользователей умерялись разработчиками, которые могли предложить только вариант Web, работающий под Windows-95/NT, и для связи с СУБД на больших машинах приходилось применять некое подобие Gateway-ODBC. Такой вариант не всегда оказывался эффективным, тем более, что протокол HTTP при каждом новом запросе требовал перезагрузки модуля Применение сервлетов в связке с СУБД решает эту проблему. Для Apache существует специальный программный компонент JServ, который также как и сам сервер в исходных кодах распространяется совершенно бесплатно. При запуске Apache автоматически стартует Java-обработчик, которому и будут передаваться на исполнение все запросы, связанные с запуском Java-программ. Наоборот, весь вывод из Java переадресуется непосредственно в Web, который аккуратным образом передает его запросившему браузеру. Скорость выполнения Java-приложений зависит от производительности компьютера, на котором сконфигурирован Web-сервер Apache. Если это, к примеру UltraSparc-3000 c Java-виртуальной машиной HotSpot, то скорость может быть очень большой, в десятки, а то и в сотни раз быстрее, чем на обычной NT-машине.


Apache, в отличие от браузеров не имеет собственной виртуальной машины Java, а настраивается на ту, которая сгенерирована для данной платформы. Такой подход чрезвычайно гибок, ибо позволяет постоянно обновлять Java-среду, наращивать библиотеку классов и ничего не изменять в настройках Apache. Впрочем, и в самих конфигурационных файлах Apache для программистов имеется масса полезных вещей, они свободно корректируются, открыты для добавлений и предоставляют гораздо больше простора для маневра по сравнению с жестко запрограммированными системами для администрирования Web-узлов, такими как Fastrack, или Java Web Server. Для того, чтобы использовать Apache во взаимодействии с Java, необходимо инсталлировать продукт Jserv, содержащий необходимые библиотеки Java-классов, затем изменить конфигурационный файл Apache Configuration, добавив в него строку: Module jserv_module mod_jserv.o

(модуль mod_jserv.c должен находиться при этом в src/директории Apache). После этого необходимо рекомпилировать Apache с помощью программы make. Затем можно изменить основной конфигурационный файл Apache httpd.conf, добавив в него строки вида: <IfModule mod_jserv.c> ServletProperties conf/servlet.properties ServletPort 8007 ServletBinary /opt1/jdk1.1.5/bin/java ServletClassPath /opt1/jdk1.1.5/lib/classes.zip ServletClassPath /opt1/local/etc/httpd/jserv/lib/servclasses.zip ServletClassPath /opt1/local/etc/httpd/jserv/classes ServletClassPath /opt1/JSDK1.0.1/lib/classes.zip ServletErrorLog logs/jserv_log ServletAlias /servlets /opt1/local/etc/httpd/ jserv/servlets ServletAuthExport Off # AddHandler jhtml-parser .jhtml # Action jhtml-parser /servlets/ org.apache.jserv.JServSSI </IfModule>

Разумеется, в каждом конкретном случае директории могут быть разными, однако, сразу после старта Apache HTTP-сервера по команде httpd, он автоматически запускает Java-обработчик, который и будет загружать и исполнять все запрошенные сервлеты, в том числе и те, которые будут работать с базами данных.Преимущество Apache при работе с базами данных заключается в том, что поскольку он, также как и Java, доступен в исходных кодах, можно эффективно использовать его расширяемую архитектуру и дополнять его различными промежуточными фильтрами на Java и на языке C, которые, по усмотрению разработчиков могут выполнять различные полезные функции.


Сервлеты на базе Java Web Server


Сервлеты являются объектами, которые образуют специфический интерфейс, с помощью которого их можно свободно встраивать в Java-ориентированные Web-сервера. В отличие от апплетов, они являются облегченными Java-объектами (без графики и GUI-компонентов), но зато, будучи кроссплатформенными и динамически загружаемыми и, используя все возможности Java, они могут использовать практически любой HTML и взаимодействовать с любым браузером. Естественно, что сервлеты можно использовать и используют для доступа к базам данных, программируя все удаленные операции с базой из браузера. В настоящее время большинство Web серверов поддерживают технологию сервлетов. Java Web-Server хорош тем, что что он наиболее полно реализует эту технологию. Стандартный Servlet-API реализован как в самом Java Web Server, так и в отдельном продукте JSDK, но начиная с версии 1.2, он включен в состав JDK. Характерной особенностью сервлетов является то, что они не требуют создания новых процессов при каждом новом запросе. Множество сервлетов выполняются параллельно в рамках одного процесса на сервере и по своей производительности превосходят как CGI, так и Fast-CGI приложения (см. Рис.3).


Рис. 3. Возможные процессы на Web-сервере.

Несмотря на то, что сервлеты используют HTTP-протокол, им нет необходимости перезагружать процесс при каждом новом запросе и это также повышает их быстродействие. К сожалению, когда вы используете сервлеты, опять-таки, возникает проблема использования кириллических символов. Дело в том, что стандартный путь прохождения данных тут не действует, потому что Web-сервер при старте запускает так называемый Java-handler, которому передает на выполнение все Java-сервлеты и обменивается вводом-выводом именно с ним через специальную библиотеку классов. Поэтому, если вы хотите получать в браузере от вашего Web-сервера, который исполняет сервлеты, кириллические строки, вам надо использовать вместо стандартных примитивов ввода/вывода некоторые специальные методы для работы со строками, например: // Определение необходимого кодификатора // в зависимости от используемого типа кодировки String dos = new String(_Cp866_); String win = new String(_Cp1251_); String iso = new String(_8859_5_); String im = new String(_Кириллический текст_); .......................................................


out.println(_<body>_); //out.write(im.getBytes(dos)); out.write(im1.getBytes(win)); //out.write(im2.getBytes(iso)); out.println(_</body></html>_);

Но и весьма эффективная функция Java - getBytes() не действует, когда вы извлекаете данные при помощи сервлетов из баз данных. Здесь необходимо применить метод, который мы уже использовали при работе с базами данных при помощи интерфейса JDBC. Кроме того, файл font.properties в каталоге $JDK_HOME/lib или в специальном каталоге вашего браузера должен быть соответствущим образом настроен. Во многих пакетах Java имеются образцы файла font.properties.ru, который можно взять в качестве основы. Если вы работаете с уже русифицированным Web-сервером, например, русской версией Apache, то он позаботится за вас и сам перекодирует данные, поступающие из базы данных от сервлета. Каким образом программируются операции с базой данных в сервере? Сервлет не накладывает никаких ограничений на использование интерфейсов с базой данных. Можно использовать обыкновенный JDBC-ODBC, или специфические драйвера ориентированные на конкретные SQL-сервера и базы данных. Рассмотрим типичный DBServlet.java, который с успехом будет выполняться как на Java Web Server, так и Web сервере Apache. /* * @(#)DBServlet.java 1.6 97/06/13 */ import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.net.*; import java.sql.*; /** * DBServlet * * Этот сервлет демонстрирует как использовать JDBC стек * и получать доступ к базам данных при помощи сервлетов. Для того, чтобы выполнить этот * сервлет, переменные CLASSPATH, LD_LIBRARY_PATH, ODBCINI * должны быть соответствующим образом установлены. */ public class DBServlet extends HttpServlet { /** * init method */ public void init(ServletConfig conf) throws ServletException { super.init(conf); } /** * service method */ public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String stack, username, password, query; Connection con; PrintStream out; /* ServletOutputStream out = res.getOutputStream();*/ // Загрузка параметров.


Именно эти параметры должны будут вводиться // в специально прорисованном окне браузера, с которым будет // взаимодействовать наш сервлет stack = req.getParameter(_stack_); username = req.getParameter(_username_); password = req.getParameter(_password_); query = req.getParameter(_query_); res.setContentType(_text/html_); out = new PrintStream(res.getOutputStream()); printPageHeader(out); // в том случае, если параметры отсутствуют if (stack == null username == null password == null query == null) { printPageFooter(out); return; } String url = _jdbc:odbc:_+stack; out.println(_<hr><h3>Previous Query</h3>_); out.println(_<pre>_); out.println(_Database Stack : _+stack); out.println(_ User ID : _+username); out.println(_ Password : _+password); out.println(_ Query : _+query); out.println(_</pre>_); try { // Найти jdbc стек. Может существовать несколько зарегистрированных драйверов Class.forName(_sun.jdbc.odbc.JdbcOdbcDriver_); //Class.forName(_jdbc.odbc.JdbcOdbcDriver_); // Получить соединение с базой данных con = DriverManager.getConnection(url, username, password); out.println(_<hr>_); out.println(_<h3>ODBC Driver and Database Messages</h3>_); checkForWarning(con.getWarnings(), out); DatabaseMetaData dma = con.getMetaData(); out.println(_Connected to _ + dma.getURL() + _<br>_); out.println(_Driver _ + dma.getDriverName() + _<br>_); out.println(_Version _ + dma.getDriverVersion() + _<br>_); // Создать и выполнить запрос. Конкретный оператор SQL // вводится удаленным пользователем в окне его браузера Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query); // Печать результатов. Они переназначаются на стандартный вывод // и поступают в браузер клиента dispResultSet(rs, out); rs.close(); stmt.close(); con.close(); out.println(_<hr>_); } catch (SQLException ex) { out.println(_<hr>*** SQLException caught ***_); while (ex != null) { out.println(_SQLState: _ + ex.getSQLState() + _<br>_); out.println(_Message: _ + ex.getMessage() + _<br>_); out.println(_Vendor: _ + ex.getErrorCode() + _<br>_); ex = ex.getNextException(); } } catch (java.lang.Exception ex) { ex.printStackTrace(); } printPageFooter(out); } /** * возврат запрошенной информации */ public String getServletInfo() { return _Это простой сервлет, который показывает как использовать JDBC_; } /* * проверка и печать информации сервера */ private void checkForWarning(SQLWarning warn, PrintStream out) throws SQLException { boolean rc = false; if (warn != null) { out.println(_<hr>*** Warning ***_); rc = true; while (warn != null) { out.println(_SQLState: _ + warn.getSQLState() + _<br>_); out.println(_Message: _ + warn.getMessage() + _<br>_); out.println(_Vendor: _ + warn.getErrorCode() + _<br>_); warn = warn.getNextWarning(); } } } /* * Показ результатов запроса в табличном html формате */ private void dispResultSet(ResultSet rs, PrintStream out) throws SQLException, IOException { int i; // метаданные используются для получения информации о схеме ResultSetMetaData rsmd = rs.getMetaData(); int numCols = rsmd.getColumnCount(); out.println(_<hr>_); out.println(_<h3>Database Columns and Data</h3>_); out.println(_<table border=3>_); out.println(_<tr>_); for (i=1; i<=numCols; i++) { out.println(_<th>_ + rsmd.getColumnLabel(i) + _</th>_); } out.println(_</tr>_); // для всех данных while (rs.next()) { out.println(_<tr>_); // for one row for (i=1; i<=numCols; i++) { dispElement(rs, rsmd.getColumnType(i), out, i); } out.println(_</tr>_); } out.println(_</table>_); } // печать одного элемента private void dispElement(ResultSet rs, int dataType, PrintStream out, int col) throws SQLException, IOException { String cp1 = new String(_Cp1251_); // в зависимости от типа данных, определяем различные типы обработки switch(dataType) { case Types.DATE: java.sql.Date date = rs.getDate(col); out.println(_<th>_ + date.toString() + _</th>_); break; case Types.TIME: java.sql.Time time = rs.getTime(col); out.println(_<th>_ + time.toString() + _</th>_); break; case Types.TIMESTAMP: java.sql.Timestamp timestamp = rs.getTimestamp(col); out.println(_<th>_ + timestamp.toString() + _</th>_); break; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: String str = rs.getString(col); // Возможно, что здесь вам понадобятся кириллические преобразования out.println(_<th>_ + str + _</th>_); break; case Types.NUMERIC: case Types.DECIMAL: java.math.BigDecimal numeric = rs.getBigDecimal(col, 10); out.println(_<th>_ + numeric.toString() + _</th>_); break; case Types.BIT: boolean bit = rs.getBoolean(col); out.println(_<th>_ + new Boolean(bit) + _</th>_); break; case Types.TINYINT: byte tinyint = rs.getByte(col); out.println(_<th>_ + new Integer(tinyint) + _</th>_); break; case Types.SMALLINT: short smallint = rs.getShort(col); out.println(_<th>_ + new Integer(smallint) + _</th>_); break; case Types.INTEGER: int integer = rs.getInt(col); out.println(_<th>_ + new Integer(integer) + _</th>_); break; case Types.BIGINT: long bigint = rs.getLong(col); out.println(_<th>_ + new Long(bigint) + _</th>_); break; case Types.REAL: float real = rs.getFloat(col); out.println(_<th>_ + new Float(real) + _</th>_); break; case Types.FLOAT: case Types.DOUBLE: double longreal = rs.getDouble(col); out.println(_<th>_ + new Double(longreal) + _</th>_); break; case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: byte[] binary = rs.getBytes(col); out.println(_<th>_ + new String(binary, 0) + _</th>_); break; } } private void printPageHeader(PrintStream out) { out.println(_<html>_); out.println(_<head>_); out.println(_<tltle> Типичный сервлет для работы с базами данных </title>_); out.println(_</head>_); out.println(_<body>_); out.println(_<center><font size=5>_ + _<b>Jeeves Database Servlet</b>_ + _</font></center>_); out.println(_<hr>_); out.println(_<form action=\_/servlet/dbServlet\_ method=\_get\_>_); out.println(_<pre>_); out.println(_ODBC DSN : <input type=textarea name=stack>_); out.println(_ User ID : <input type=textarea name=username>_); out.println(_ Password : <input type=textarea name=password>_); out.println(_ SQL Query : <input type=textarea name=query>_); out.println(_</pre>_); out.println(_<input type= submit>_); out.println(_</form>_); } private void printPageFooter(PrintStream out) { out.println(_</body>_); out.println(_</html>_); out.flush(); } }



В этой программе содержатся пакеты классов для поддержки сервлетов - javax.servlet.* и javax.servlet.http.*, которые находятся в специальном продукте фирмы JavaSoft JSDK1.0.1 или непосредственно в JDK1.2.

Главная вещь, которую необходимо при этом понять, - это каким образом извлекаются переданные сервлету аргументы на вводе и каким образом передаются ответные параметры на выводе. public void service (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { ... }

Специальный метод request содержит список параметров, которые могут быть извлечены при помощи HttpServletRequest::getParameterNames метода. stack = req.getParameter(_stack_);

возвращает вам значение вами же определенного в htm-форме параметра stack, в котором вы можете задавать с клавиатуры имя ODBC-источника (ODBC DSN).

Можно установить специальный цикл обработки для извлечения каждого параметра, переданного из HTML-формы, когда она направлена для обработки к сервлету: while ( values.hasMoreElements() ) { ... }

Имя и значение каждого извлекаемого параметра можно получать во время работы цикла. String name, value; name = (String)values.nextElement(); value = req.getParameter (name);

Этих знаний вполне достаточно для того, чтобы начать писать простые сервлеты, расширяющие функциональность JavaServer"а для обработки форм, вместо того, чтобы писать cложные CGI. Имеется, впрочем, еще одна проблема, которую также необходимо изучить - обработка событий и исключительных ситуаций. Убедитесь, что вы специфицировали этот сервис и init методы в вашем подклассе HttpServlet как ServletException: public void init (ServletConfig conf) throws ServletException ... public void service (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException ...

Внутри DBServlet сервлета метод service может использовать один или несколько блоков try/catch, которые обеспечивают пользователю или программисту обработку событий, связанных с некоторыми неверными действиями или ситуациями.В первом блоке try пользователь может обработать ситуацию при возникновении проблемы соединения с сервером базы данных или выполнении sql-запроса. Второй блок try можно использовать по своему усмотрению, например, при записи результатов в файл и последующей проверке - должным ли образом он закрыт перед выходом из обслуживающей процедуры. Если нет - в стандартное устройство вывода выдается соответствующая трассировка.

Эту программу легко модифицировать в соответствии с вашими нуждами и получать не только содержимое таблиц и колонок, но и любые метаданные Потому в стандартном пакете java.sql содержится гораздо больше методов, чем те, которые предлагают стандартные средства для построения стандартных ODBC-приложений.


кому уже сейчас не терпится


Те, кому уже сейчас не терпится посмотреть на настоящие живые компоненты ActiveX, могут, вооружившись броузером Internet Explorer, познакомиться с небольшой , отобранных фирмой Microsoft (если вы почему-либо не хотите расставаться с броузером Netscape, вам придется сначала установить для него специальный модуль, о котором речь пойдет ниже). Если же вам интереснее разобраться сначала в том, как использовать это новое средство в ваших собственных страницах, - читайте дальше.
Органы управления ActiveX подключаются к HTML-документам с помощью тега <OBJECT>, который предложен в одном из и поддерживается пока только броузером Internet Explorer. Назначение этого тега (как и схожего с ним тега <EMBED>, применяемого в Netscape Navigator для вызова подключаемых модулей) - интеграция в HTML инородного материала, обрабатываемого независимыми программами. Вот полный синтаксис этого элемента HTML:
<OBJECT ALIGN=BASELINE|CENTER|LEFT|MIDDLE|RIGHT|TEXTBOTTOM|TEXTMIDDLE|TEXTTOP BORDER=число
CLASSID=URL
CODEBASE=URL
CODETYPE=MIME-тип
DATA=URL
DECLARE HEIGHT=число
HSPACE=число
ID=идентификатор
NAME=идентификатор
SHAPES STANDBY=текст
TYPE=MIME-тип
USEMAP=URL
VSPACE=число
WIDTH=число
> </OBJECT>
Некоторые из перечисленных атрибутов аналогичны одноименным атрибутам известного тега <IMG>, поэтому здесь мы их рассматривать не будем. Вот полное описание атрибутов, специфических для тега <OBJECT>:
CLASSID=URL
С помощью этого атрибута указывается идентификатор класса вызываемого органа управления. Каждый OCX-модуль и, следовательно, каждый орган управления ActiveX обязан иметь свой уникальный идентификатор класса. Программисты, знакомые с технологией OLE, уже встречались с этим идентификатором, который обычно обозначается сокращением CLSID и представляет собой довольно длинную цепочку шестнадцатеричных цифр - что-нибудь вроде "017C99A0-8637-11CF-A3A9-00A0C9034920".
Но почему же в синтаксисе этого атрибута стоит "URL"? Дело в том, что тег <OBJECT> может использоваться для подключения не только органов управления ActiveX, но и почти любых программных или информационных объектов - в том числе и таких, которые распознаются не по "идентификаторам классов", а как-нибудь иначе.


Чтобы дать понять броузеру, как воспринимать строку - значение атрибута CLASSID, строка эта строится по тем же правилам, что и URL-адреса. (Это позволяет, в частности, записать в этот атрибут обычный URL какого-нибудь файла в WWW.) Значение CLASSID для органов управления ActiveX состоит из двух частей, соединенных двоеточием: левая часть содержит слово "clsid", а правая - собственно идентификатор класса. Пример: CLASSID="clsid:017C99A0-8637-11CF-A3A9-00A0C9034920"
Как и в большинстве подобных случаев, кавычки вокруг значения атрибута можно опустить (хотя делать это не рекомендуется). Для органов управления ActiveX этот атрибут обязателен.
CODEBASE=URL
В этом атрибуте указывается URL-адрес (на сей раз уже вполне настоящий, с "http:" или "ftp:") файла, содержащего вызываемый орган управления и доступного для получения с одного из серверов Интернета. К этому серверу броузер обратится в том случае, если не сможет найти копию данного органа управления на компьютере пользователя. URL-адресов в этом атрибуте можно перечислить несколько - на тот случай, если какой-то из серверов будет почему-либо недоступен.
Этот же атрибут позволяет указывать для органов управления ActiveX требуемый номер версии. Например, если написать CODEBASE="http://activex.microsoft.com/controls/ iexplorer/iegrad.ocx#Version=4,70,0,1161"
то попытка получить данный модуль ActiveX из Интернета предпринимается не только в том случае, когда на компьютере пользователя его нет, но и тогда, когда орган управления установлен, но имеет более старый номер версии, чем тот, что указан в атрибуте CODEBASE (в нашем примере требуется версия не старее 4.70.0.1161).
CODETYPE=MIME-тип

TYPE=MIME-тип
Эти два необязательных атрибута позволяют указать типы (в терминах стандарта MIME) тех файлов, на которые ссылаются атрибуты CLASSID (атрибут CODETYPE) и DATA (атрибут TYPE). Для органов управления ActiveX атрибут CODETYPE, если он присутствует, должен иметь значение "application/x-oleobject".


DATA=URL
С помощью этого атрибута указывается местонахождение файла данных, который может понадобиться для работы данному органу управления. Для некоторых органов управления ActiveX этот атрибут является обязательным. Кроме того, с помощью атрибута DATA можно включать прямо в HTML-файл в закодированном виде сам файл, содержащий орган управления (этим можно пользоваться только для очень небольших по объему файлов).
DECLARE
Добавление этого пустого атрибута заставит тег <OBJECT> произвести только объявление, но не создание объекта. При этом в память броузера записывается весь набор атрибутов и параметров объекта, но никакой перекачки файлов или запуска программ не происходит. Действительное создание этого объекта откладывается до того момента, пока кому-нибудь (другому объекту или сценарию) не потребуется обменяться данными с работающей копией объекта. Уловив эту потребность, броузер тут же попытается материализовать затребованный объект в соответствии с хранящимися в его памяти спецификациями.
ID=идентификатор
Атрибут ID позволяет приписать создаваемому объекту имя в виде какого-то идентификатора. Обращение к этому объекту со стороны других объектов или сценариев возможно только через указание этого имени. Кроме того, указанный здесь идентификатор может использоваться как привязка для гипертекстовых ссылок на объект (т.е. может стоять после символа "#" в URL-адресе).
Важно понимать, что если CLASSID указывает на тип объекта (в терминах объектно-ориентированного программирования - на класс, экземпляром которого является объект), то ID представляет собой уникальное имя конкретного экземпляра объекта. Иными словами, можно создать сколько угодно тегов <OBJECT> с одним и тем же значением CLASSID, но значения ID у них обязательно должны различаться.
NAME=идентификатор
С помощью этого необязательного атрибута создаваемый объект может внести свой вклад в данные, которые броузер отошлет на сервер после заполнения пользователем HTML-бланка (для этого тег <OBJECT> должен находиться внутри пары тегов <FORM> ... </FORM>).


Отправляемые данные будут содержать информацию, полученную броузером от объекта (понятно, что далеко не каждый объект годится для такой операции) в паре с идентификатором, указанным в атрибуте NAME.
SHAPES
Этот пустой атрибут приказывает броузеру наложить на прямоугольник, занимаемый объектом, карту (map), так чтобы отдельные регионы этого прямоугольника служили рабочими частями гипертекстовых ссылок. Координаты этих регионов и URL-адреса ссылок для них указываются с помощью тегов <A> со специальными дополнительными атрибутами, которые должны располагаться между <OBJECT> и соответствующим ему </OBJECT>. Это дает возможность, не теряя совместимости со старыми броузерами, с помощью тега <OBJECT> избавиться от необходимости снабжать все изображения-карты текстовыми эквивалентами.
STANDBY=текст
В этом атрибуте можно указать текстовую надпись, которая будет видна в прямоугольнике, отведенном объекту, пока сам объект будет загружаться и запускаться.
Помимо информации, передаваемой в атрибутах тега <OBJECT>, органам управления для работы требуется, как правило, набор каких-то дополнительных параметров. Эти параметры передаются с помощью тегов <PARAM>, которые вставляются между <OBJECT> и соответствующим ему </OBJECT>. Каждый тег <PARAM> имеет пару атрибутов NAME и VALUE, с помощью которых задается одна пара "имя-значение", т.е. присваивается значение одному именованному параметру. Разумеется, список возможных параметров и набор допустимых значений - свои у каждого органа управления и указываются в документации к нему.
Как подсказывает само название тега <OBJECT>, каждый случай употребления этого тега в HTML-файле инициирует создание экземпляра объекта - в том смысле, какой это слово имеет в объектно-ориентированных языках программирования. Подобно любому другому, созданный таким образом объект имеет определенные свойства (properties), методы (methods) и события (events), набор которых свой у каждого органа управления.


Единое информационное пространство Web-страницы позволяет напрямую обращаться к этим свойствам и методам как другим объектам - органам управления ActiveX, так и встроенным в HTML-документ сценариям на любом из поддерживаемых языков (как известно, Internet Explorer сейчас поддерживает два языка для написания сценариев - VBScript и JavaScript).
Переменные - свойства объекта всегда совпадают (и по значению, и по обозначению) с теми параметрами, которые передаются ему с помощью тегов <PARAM>. Методы объекта - это функции, вызов которых позволяет выполнить какие-то действия, специфические для данного класса объектов. Так, почти все органы управления ActiveX содержат метод AboutBox, выводящий на экран окно с информацией о фирме-разработчике, версии и дате выпуска данного модуля, и метод Repaint, заставляющий модуль обновить изображение в отведенной ему области (к примеру, после изменения каких-то параметров). Доступ к свойствам и методам объекта в языке JavaScript осуществляется через идентификатор, присвоенный объекту атрибутом ID. Чтобы ыполучить значение какого-то свойства объекта, достаточно написать имя-объекта.имя-свойства
а чтобы вызвать принадлежащий объекту метод - имя-объекта.имя-метода (параметры метода)
Несколько сложнее обстоит дело с доступом к событиям объекта. Вы, вероятно, знаете, что если с объектом связано некое событие, то при его наступлении (например, при щелчке мышью над объектом или по истечении какого-то периода времени) управление получает специальный фрагмент кода - обработчик события (event handler). Обработчики для тех событий, которые вас интересуют, вы должны самостоятельно написать, а затем связать их с нужными событиями тех или иных объектов. До сих пор привязка обработчиков к событиям в программах на JavaScript была возможна единственным способом - с помощью специальных атрибутов в элементах HTML, определяющих объект, к которому относится событие. Например, чтобы предусмотреть какую-то реакцию на нажатие кнопки, нужно добавить к тегу <INPUT>, с помощью которого эта кнопка создается, следующий атрибут: onClick="фрагмент сценария"
К сожалению, с тегом <OBJECT> такой метод не работает - даже если создаваемый с его помощью орган управления способен реагировать на щелчок мыши, добавление к тегу атрибута onClick нужного эффекта не даст. Чтобы решить эту задачу, нужно записать обработчик события в отдельной паре тегов <SCRIPT> ... </SCRIPT>, добавив к открывающему тегу следующую пару атрибутов:
FOR="имя объекта"
EVENT="имя события"
Имя объекта - это тот идентификатор, который был ему приписан с помощью атрибута ID (см. выше). Как правило, имена событий (набор которых свой у каждого органа управления) не содержат префикса "on" - так, событие щелчка мыши всегда обозначается идентификатором Click, а не onClick.

Система FLORID


Система FLORID [HLLS97, LHL+98] - реализация прототипа дедуктивного и объектно-ориентированного формализма F-логики [KLW95]. Чтобы использовать FLORID как механизм обработки запросов для Web, документ Web моделируется следующими двумя классами:

url::string[get => webdoc]. webdoc::string[url => url; author => string; modif => string; type => string; hrefs@(string) => url; error =>> string].

Первая из этих деклараций вводит класс url, подкласс string с единственным методом get. Нотация get => webdoc означает, что get - метод, вырабатывающий единственное значение (single-valued), который возвращает объект типа webdoc. Метод get является определяемым системой. Результатом вызова u.get для url u в заголовке дедуктивного правила является выборка из Web документа с данным URL и кэширование его в локальной базе данных FLORID как объекта webdoc с идентификатором объекта u.get.

Класс webdoc с методами self, author, modif, type, hrefs и error моделирует основную информацию, общую для всех документов Web. Нотация hrefs@(string) = >> url означает, что многозначный метод hrefs получает string как аргумент и возвращает множество объектов типа url. Идея состоит в том, что, если d есть webdoc, то d.hrefs@(aLabel) возвращает URL всех документов, на которые указывают связи, помеченные как aLabel внутри документа d.

По необходимости могут декларироваться подклассы документов с использованием наследования F-логики, например:

htmldoc::webdoc[title => string; text => string].

Вычисление во FLORID выражается наборами дедуктивных правил. Например, приведенная ниже программа осуществляет выборку из Web множества всех документов, достижимых непосредственно или косвенным образом из URL по связям, метки которых содержат строку "база данных".

(<www.cs.toronto.edu>:url).get.(Y:url).get <-(X:url).get[hrefs@(L)=>>{Y}], substr(<база данных>,L).

FLORID обеспечивает мощный формализм для управления слабоструктурированными данными в контексте Web.


Однако, он не обеспечивает в настоящее время конструирования в результате вычисления новых сайтов. Результат всегда представляет собой некоторое множество объектов F-логики в локальной памяти.

Языки ULIXES и PENELOPE

В проекте ARANEUS [AMM97b] процесс обработки запросов и реструктуризации разбивается на две фазы. На первой фазе для построения реляционных представлений над Web используется язык ULIXES. Эти представления могут далее анализироваться и интегрироваться с использованием стандартных технологий баз данных. По запросам, сформулированным на языке ULIXES, производится выборка реляционных данных из экземпляров схем страниц, которые определены средствами модели ADM, с интенсивным использованием выражений путей без символа <*> (star-free). Вторая фаза заключается в генерации гипертекстовых представлений данных с использованием языка PENELOPE. Проблемы оптимизации запросов для реляционных представлений, поддерживаемых над множествами страниц Web, например, построенных средствами ULIXES, обсуждаются в [MMM98].

Интерактивные интерфейсы запросов

Все языки, рассмотренные в предыдущих двух подразделах, слишком сложны для непосредственного применения интерактивными пользователями, точно так же, как и SQL. Предполагается, что они, подобно SQL, должны использоваться, главным образом, как инструментальные средства программирования. Однако проводились работы по созданию интерактивных интерфейсов запросов, пригодных для случайных пользователей. Одним из них является Dataguides [GW97] - интерактивное средство запросов для слабоструктурированных данных, основанное на иерархических "выжимках" (summaries) графа данных. Расширения для поддержки запросов в отдельных сложных Web-сайтах рассмотрены в [GW98]. Система, описанная в [HML+98], поддерживает запросы, которые сочетают мультимедийные возможности, например, схожесть с данным эскизом или изображением, возможности работы с текстами, такие как поиск по ключевым словам, а также семантику предметной области.

Теория запросов в Web



Определяя семантику языков запросов первого поколения для Web, можно немедленно обнаружить, что легко формулируемые запросы вида "перечислить все документы Web, которые не указывают ни на какие другие документы", могут быть довольно трудными для исполнения. В связи с этим обстоятельством возникают, естественно, вопросы о вычислимости запросов в таком контексте. Абитебул и Виану [AV97a], а также Мендельсон и Мило [MM97] предложили формальные способы категоризации запросов в Web, в соответствии с тем, могут ли они в принципе быть вычисленными или нет. Ключевая идея заключается, по существу, в том, что единственный возможный способ доступа в Web - это навигация по связям из известных стартовых точек. (Заметим, что специальным частным случаем является навигация по связям, исходя из больших совокупностей стартовых точек, называемых индексными серверами или поисковыми машинами). Абитебул и Виану [AV97b] обсуждают также фундаментальные проблемы, возникающие при оптимизации запросов, связанных с обходом путей. Михайла, Мило и Мендельсон [MMM97] показывают, как анализировать запросы в WebSQL на основе максимального числа Web-сайтов. Флореску, Леви и Сучу [FLS98] описывают алгоритм для запросов по содержанию, для запросов с правильными выражениями путей, который затем используется для проверки ограничений целостности на структуре Web-сайтов [FFLS98].


Системы XML/EDI


Комбинация XML и EDI предполагает для XML/EDI разработку предложений основных методов описания и кодирования EDI сообщений посредством XML обработки. Формы, обрабатывающие XML документы должны быть согласованы, чтобы осуществлять взаимодействие с существующими XML/EDI системами. Для этого они должны иметь возможность генерировать EDIFACT сообщения, осуществлять их анализ и отображение.

XML/EDI предлагает пользователям, использующих текущие стандарты пути решения возможных проблем и может быть интегрировано в существующие EDI системы путем:

Разработки форм для приложений пользователя, способных генерировать EDI сообщения Создания форматов EDI сообщения для их передачи между компьютерами по Интернет, или через сети с добавленными услугами (VANs) Разработки пользовательских шаблонов для интерпретации согласованных правил на компьютере получателя с помощью стандартных программ просмотра (броузеров)

XML/EDI представляет нечто больше, чем прямой перенос XML документов в системы EDI. В рамках построения XML/EDI представляется слияние пяти технологий (XML, EDI, Templates, Agents и Repository), которые существенно расширят существующие возможности информационной системы. Каждый из этих компонент добавляет свои специфические возможности.

Использование технологий XML/EDI реализует следующие цели:

Сделать EDI универсально допустимыми, используя свободно распространяемый код и синтаксис SQL (XQL) Осуществить разработку "последующих" EDI - сообщений таким образом, чтобы они были полностью совместимы с существующими X12 и UN/EDIFACT стандартами Осуществление, по возможности, единой трансляции сообщений X12 и UN/EDIFACT

На рис. 2 представлены составные части технологий XML/EDI:

Рис. 2 Составные части XML/EDI технологий

Более подробно про каждую из составных частей:

XML. В основе обмена документами лежат транспортные протоколы, используемые в Интернет. С помощью заранее определенных тэгов определяется объектная модель данных, которая в последствии заполняется данными и передается в качестве электронного документа.


Существующее идентификаторы сегментов EDI заменяются тэгами XML, или часть данных из EDI сегмента добавляются в тэги в качестве параметров.

EDI. Разработанные в EDI системах стандарты способны представлять данные в простом формате. Эти данные однозначно интерпретируются на принимающей и передающей стороне. XML/EDI позволит обеспечить 100 % совместимостью с существующими EDI системами, используя при этом обмен EDIFACT сообщениями. Разработка протоколов XML/EDI позволяет использовать уже существующие EDI системы, что не потребует новых капиталовложений для разработки глобальных систем.

Templates (Шаблоны) - это набор определенных правил, которые осуществляют управление процессом, как на клиентской, так и на серверной стороне. С помощью шаблонов можно выразить в XML все особенности процесса, который должен быть выполнен. Шаблон могжет быть загружен как с удаленного источника, откуда пришел XML документ, так и быть его составной частью. Шаблоны используют Document Type Definitions (DTD's), по которым определяется объектная модель данных. Удаленное использование (DTD's) позволит всем клиентским приложениям однозначно определить используемую модель данных.

Agents (Агенты) интерпретируют шаблоны, чтобы интерактивно выполнить необходимые транзакции и взаимодействовать с пользователем. Агенты могут быть реализованы как аплеты Java или внедренные объекты ActiveX. Разбор структуры XML может осуществляться Агентом прямо на компьютере клиента и использовать при этом необходимые для пользователя данные и их представление. Первоначально агенты будут управляться Шаблонами и предоставлять пользователю некоторые дополнительные возможности. Предполагается, что позже будут разработаны соответствующие протоколы для Агентов.

Repository (хранилище) - совместно используемые в Интернете общедоступные словари - которые уже используются в традиционных EDI системах. Данные словари позволяют пользователям найти значение и область определения EDI элементов. Совместно используемые общие словари обеспечивают автоматические поисковые таблицы более гибким механизмом поиска.


Данный компонент обеспечит семантическую основу для EDI транзакций.

Можно выделить следующие основные принципы построения XML/EDI:

XML используется как макет " моделирование обмена данными " XSL используется как уровень "представления" Возможность интеграции с традиционными методами EDI Использование маршрутизациии по IP, а текже использование протоколов HTTP, FTP и SMTP Централизованное представление документа и методология обработки Протоколирование приема/отправки документов Использование современных инструментальных средств программирования (Java и ActiveX) Разделение данных и программ Использование технологии агента для манипулирования данными, синтаксического анализа, отображения, поиска и т.д.

Определенные XML/EDI компоненты сформированы на основе существующих протоколов передачи и обработки кодированных в XML данных.



Рис 3. Уровни Интерфейсов XML/EDI

На рисунке представлены следующие интерфейсы уровней XML/EDI:

Использование стандартных транспортирных механизмов данных по Интернет и хранения файлов Форматы представления данных и передачи сообщения Синтаксис XML данных Правила грамматического разбора XML документа или создание объектной модели Правила XSL представления, связь со скриптами и уровнем разбора объекта Использование правил управления данными для пользовательских приложений и интерфейсов баз данных

Сегодня уже доступны синтаксические XML анализаторы, программы просмотра XML-документов (броузеры), программы разметки страниц и библиотеки программ. Предполагается использование специальных XML/EDI компонент встаивать в существующие программные продукты. Это позволит значительно ускорить создание новых приложений, реализующих XML/EDI.

Первичные компоненты XML/EDI представляют общей язык описания и синтаксические правила и включают:

таблицу определения данных - DTD Базу (хранилище) данных - Repositories Сегменты и элементы данных (т.e. EDIFACT, X12, или BSI директории) Базу бизнес объектов Страницы торговых партнеров (База данных предприятий).



На рис. 4 представлены возможные варианты подключения отдельных компонентов XML/EDI. На данной схеме выделены в отдельные компоненты: удаленный пользователь, бизнес приложения, существующие EDI-системы, публичные директории и специальные словари и базы данных.



Рис 4 Связи в XML/EDI

Конечный пользователь посредством WEB-броузера может взаимодействовать с любыми компонентами системы, используя XML-представления и XQL запросы.

Хотелось бы отметить о возможности более интересующегося читателя подчерпнуть более подробную информацию на следующих серверах:

- рекомендации Торговой Палаты
- EDI группа
- консультативная EDI группа
- Обзор публикаций по EDI
- рабочая группа по защите UN/EDIFACT (SJWG)
- EDI стандарты
- EDI стандарты
- ассоциация пользователь электронными сообщениями
- введение в XML, статьи по XML
- рекомендации группы W3 по использованию XML
- руководство по XML
- публичный сервер пользователей XML
- публичный сервер пользователей XML
- сервер группы XML/EDI
- разработки Microsoft в области применения XML
- Руководство по применению XML в системах EDI
-Европейский XML/EDI пилотный проект
- пилотные прокты Программы TEDIM
- электронный бизнес
- электронная коммерция
- бизнес через WEB


because of the copyright nature


=1= #!/usr/bin/perl =2= =3= use CGI; # must be version 2 or higher =4= use News::NNTPClient; =5= use MIME::Base64; =6= =7= $nntpserver = "news.teleport.com"; # location of news server =8= =9= ## because of the copyright nature of this material, you should =10= ## put this script in a directory that has an appropriate htaccess file. =11= =12= @groups = ( =13= ["clari.living.comics.bizarro", "Bizarro"], =14= ["clari.living.comics.cafe_angst","Cafe Angst"], =15= ["clari.living.comics.doonesbury","Doonesbury"], =16= ["clari.living.comics.forbetter","For Better or For Worse"], =17= ["clari.living.comics.foxtrot","Foxtrot"], =18= ["clari.living.comics.ozone_patrol","Ozone Patrol"], =19= ["clari.editorial.cartoons.toles","Toles"], =20= ["clari.editorial.cartoons.worldviews","Worldviews"], =21= ["clari.news.photos","News photos (not a comic, but handy)"], =22= ); =23= =24= $Q = new CGI; =25= $Qself = $Q->self_url; =26= =27= unless ($group = $Q->param('group')) { # nothing at all, give index =28= $links = join "\n", =29= map { "<p><a href=\"$Qself?group=$_->[0]\">$_->[1]</a>" } @groups; =30= =31= print <<"GROK"; q/"/; =32= @{[$Q->header]} =33= @{[$Q->start_html('Comics','merlyn@stonehenge.com')]} =34= <h1>Read the Comics</h1> =35= <p>Select the group you want to read: =36= <HR> =37= $links =38= <HR> =39= <p>Please respect the copyrights and license agreements of this service. =40= @{[$Q->end_html]} =41= GROK =42= q/"/; =43= exit 0; =44= } =45= =46= unless ($article = $Q->param('article')) { # group but no art, give group =47= $N = new News::NNTPClient($nntpserver,119,0); =48= for ($N->xover($N->group($group))) { =49= ($numb,$subj) = split /\t/; =50= $links .= "<p><a href=\"$Qself&article=$numb\">$subj</a>\n"; =51= } =52= =53= print <<"GROK"; q/"/; =54= @{[$Q->header]} =55= @{[$Q->start_html('Comics','merlyn@stonehenge.com')]} =56= <h1>Read the Comics</h1> =57= <p>Select the article you wish to view: =58= <HR> =59= $links =60= <HR> =61= <p>Please respect the copyrights and license agreements of this service. =62= @{[$Q->end_html]} =63= GROK =64= q/"/; =65= exit 0; =66= } =67= =68= ## $group and $article both valid: =69= $N = new News::NNTPClient($nntpserver,119,0); =70= $N->group($group); =71= @art = $N->article($article); =72= shift @art while @art and $art[0] !~ /^Content-Type: (image\/[-a-z]+)/; =73= $type = $1; =74= shift @art while @art and $art[0] !~ /^\s*$/; =75= pop @art; # heh =76= $gif = decode_base64(join "", @art); =77= print "Content-type: $type\n\n"; =78= print $gif; =79= exit 0;

Тип события, которое будет


Элемент
Onevent
Атрибуты:
type - Тип события, которое будет обрабатываться
Существует четыре типа событий:
onenterbackward

Сработает при выборе элемента "prev"
onenterforward

Сработает при вызове карты
onpick

Сработает при выборе опции в списке элемента "select"
ontimer

Сработает по истечении времени у элемента "timer". <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN""http://www.wapforum.com/DTD/wml_1.1.xml"> <wml> <card id="start"> <do type="accept"> <go href="two"/> </do> <p>Choose Accept.</p> </card> <card id="two"> <do type="accept"> <go href="three"/> </do> <onevent type="onenterbackward"> <prev/> </onevent> <p>Choose Accept</p> </card> <card id="three"> <do type="accept"> <prev/> </do> <p>Choose Accept.</p> </card> </wml>

Сохранение текста сессии


После установления связи с удаленной машиной весь текст, который появляется на экране в процессе работы может быть запомнен в файле персонального компьютера или выведен на принтер.

На то, что текст сессии сохраняется указывает соответствующий флажок Capture в 25й строке экрана. Такой флажок устанавливается и убирается по Alt+C. Capture ON может быть установлен только для одной сессии.

Сохранение текста происходит в так называемом Capture файле на PC пользователя. Этот файл никогда не удаляется, запись в него всегда происходит в режиме добавления. Имя Capture файла устанавливается в Config.tel, по умолчанию это capfile. Имя capture файла может быть изменено также и в процессе работы NCSA Telnet на время этой работы: через меню параметров, вызываемое по Alt+P.

Именем capture файла может быть также prn (принтер), тогда текст сессии будет распечатываться. Но, если принтер случайно оказался не в ON-LINE, то будет выведено сообщение:

Error, A(bort), R(etry), I(gnore)

При этом ответ A может вызвать завершение Telnet для всех сессий.

Независимо от того, установлен ли Capture флаг, можно сохранить в Capture файле копию экрана текущей сессии по Alt+D.



Создаем деку.


В этом примере, мы начнем создавать деку, которая позволяет нам сначала выбрать имя пользователя из предложенного списка, затем ввести пароль после чего выводит на экран полученные данные.

<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> <wml> <card id="Login" title="Login"> <do type="accept" label="Password"> <go href="#Password"/> </do> <p> UserName: <select name="name" title="Name:"> <option value="John Doe">John Doe</option> <option value="Paul Smith">Paul Smith</option> <option value="Joe Dean">Joe Dean</option> <option value="Bill Todd">Bill Todd</option> </select> </p> </card> <card id="Password" title="Password:"> <do type="accept" label="Results"> <go href="#Results"/> </do> <p> Password: <input type="text" name="password"/> </p> </card> <card id="Results" title="Results:"> <p> You entered:<br/> Name: $(name)<br/> Password: $(password)<br/> </p> </card> </wml>

Как вы наверно уже заметили, вначале примера идет пролог, в котором мы определяем версию XML и DTD для нашего документа. Затем следует элемент <wml>, дека которая содержит три карты: Login, Password и Result. Каждая из этих карт определяется с использованием элемента <card>. Поскольку карты Login и Password определяют события, они используют элемент <do type="accept"> для определения события которое произойдет, когда пользователь закончит ввод.

Если мы определяем элемент <do> типом "accept" он появляется на экране в качестве опции

Выбор этой опции приведет к анализу введенной пользователем информации.

Атрибут "href" тега <go> работает так же, как и в элементе <a> из HTML. Также как и в HTML, для того, чтобы на экран вывелась другая карты из активной деки, на нее надо сослаться используя символ "#" перед именем карты.

<go href="#result"/>

Эта карта обрабатывает пользовательский ввод и используя определенные в предыдущей карте переменные выводит их содержимое на экран. Вызов переменных осуществляется следующим образом:

$(variable_name)



Создание базы данных


Теперь нам необходимо установить соединение с СУБД MySQL и создать нашу базу данных. Ниже мы покажем, как сделать это из командной строки. Однако существует множество систем управления, или менеджеров СУБД MySQL, которые позволяют администрировать ее, используя дружественный графический интерфейс.

Прежде всего вам обязательно следует знать основы языка запросов SQL (Structured Query Language). В поставку СУБД MySQL входит полное описание поддерживаемой спецификации SQL. Этот язык несложен для постижения, поскольку его операторы и их конструкции легко понять и запомнить. Для работы вам потребуются операторы создания (CREATE или INSERT), выборки (SELECT) и удаления (DROP или DELETE) данных, а также их изменения (UPDATE, MODIFY). В конкретных примерах мы воспользуемся только некоторыми из них.

Чтобы не рассматривать установку пользовательских учетных записей (user accounts) и назначение необходимых прав доступа, предположим, что вы используете учетную запись администратора (root).

Шаг 1

Откройте терминальное окно (если вы работаете в графической оболочке X Window ОС Linux или в ОС Windows 9x/NT/2000) и установите соединение с СУБД MySQL, введя в командной строке mysql. В ответ вы должны получить приглашение для ввода команд mysql>.

Шаг 2

Создадим нашу базу данных, введя:

CREATE DATABASE db_website;

После ввода каждой команды не забывайте печатать символ (;). Он очень важен, поскольку посылает MySQL сигнал конца ввода команды.

Шаг 3

Далее необходимо послать команду, указывающую системе MySQL, какую конкретно базу данных мы собираемся использовать. Введите:

use db_website;

Шаг 4

Создадим таблицу tbl_news_items, где определим тип данных, которые будут храниться в ее полях. Введите:

1. CREATE TABLE tbl_news_items ( 2. col_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 3. col_title VARCHAR(100), 4. col_author VARCHAR(100), 5. col_body TEXT, 6. col_date DATE 7. );

Шаг 5

Теперь, когда мы создали таблицу для хранения наших данных, нам нужно заполнить ее какими-то примерными данными. Заметьте, что в нижеследующей команде мы не будем определять поле col_id, потому что оно заполняется автоматически по мере добавления новых данных. Также имейте в виду, что синтаксис для даты — <год/месяц/день>. Итак, в командной строке mysql> введите следующую команду.

8. INSERT INTO tbl_news_items (col_title, _ col_author, col_body, col_date) 9. VALUES ( 10. ‘Мой первый пресс-релиз’, 11. ‘Ваше Имя’, 12. ‘Этот пресс-релиз хранится в БД MySQL’, 13. ‘2001/4/15’ 14. );

Введите еще несколько подобных запросов для вставки. Чтобы просмотреть то, что хранится в базе данных, в командной строке mysql> введите:

SELECT * FROM tbl_news_items;



Создание динамического сайта


Первое, что нужно для создания динамического сайта, — это Web-сервер, например Apache.

Web-сервер может использоваться для обслуживания электронного магазина, сервера новостей, поискового механизма, системы дистанционного обучения и даже для всей совокупности перечисленных сфер. Выбор Web-сервера зависит от того, каким видом деятельности частное лицо или организация собирается заниматься в Интернете.

Немногие из принимаемых в бизнесе стратегических решений столь же значимы, как выбор платформы для Web-сервера. Характеристики сервера — это чрезвычайно важный фактор, определяющий надежность узла, его «отзывчивость» на запросы клиентов, а также то, какие усилия необходимо предпринимать для поддержания его в рабочем состоянии. При правильном выборе компонентов и качественном проекте Web-узел может стать для клиентов и партнеров новым, более удобным способом взаимодействия с вашей компанией. Перегрузка Web-сервера может привести к тому, что сервер баз данных или какой-либо иной ресурс станет недоступным для клиентов.

Крупные компании до недавнего времени делали ставки на Microsoft Internet Information Server, Netscape FastTrack, IBM WebSphere, а Apache в основном использовался небольшими компаниями. Однако сейчас ситуация несколько изменилась, и Apache начинает поддерживать работоспособность некоторых крупных Интернет-проектов, в частности Yahoo.

Полную версию статьи вы можете найти на нашем .

Apache предоставляет богатые возможности, позволяющие настроить Web-сервер в соответствии с потребностями индивидуальных и корпоративных пользователей. Настройка производится с помощью директив, содержащихся в конфигурационных файлах. Apache позволяет создавать виртуальные Web-узлы, а также выполняет функции proxy-сервера. Если нужно предоставить доступ к содержимому сервера лишь ограниченному кругу лиц, Web-сервер можно настроить так, чтобы при обращении к указанным каталогам сервер проверял регистрационные имена и пароли в собственной или в одной из подключенных к нему баз данных.




Далее вам нужно решить, как вы собираетесь хранить информационное наполнение (контент), которое отображается на Web-странице. В данной статье на конкретном примере мы покажем, как создать базу данных в СУБД MySQL, которая позволит нам разбить Web-контент на таблицы, содержащие поля и записи с данными. Поле — это дискретная единица данных в таблице. Например, мы можем создать таблицу tbl_news_items с полями col_title, col_date, col_fullstory, col_author. СУБД MySQL — отличный выбор для создания такой базы данных вследствие простоты в использовании и администрировании, свободной распространяемости для разных платформ, включая Linux и Windows, и быстро растущей популярности.

После этого мы создадим динамические шаблонные страницы на HTML. Чтобы разработать приложения для взаимодействия с базой данных и шаблонами, мы воспользуемся языком Perl.

На самом деле нам необходимо создать три Perl-программы, или скрипта: один будет отображать ссылки на все имеющиеся пресс-релизы (pr-list-dbi.pl), другой — содержимое выбранного пресс-релиза (pr-content-dbi.pl), а третий позволит нам добавить свежий пресс-релиз в базу данных (pr-add-dbi.pl). Работу по верстке можно возложить на любимый HTML-редактор, например, Allaire HomeSite (). Только помните, что при создании шаблона необходимо оставлять пустые области, в которые будет вставляться динамическое наполнение (естественно, переменной длины).

После разработки общего дизайна для своих пресс-релизов просто вставьте в указанные выше пустые области специальные ключевые слова (см. об этом ниже). Как только пользователь запросит какой-либо пресс-релиз, Web-сервер обработает Perl-код и заменит ключевые слова в шаблонах информационным наполнением, извлеченным из базы данных, то есть каким-то конкретным пресс-релизом.

И последнее, что нужно сделать, — загрузить ваши шаблоны на Web-сервер в определенные директории. Можно воспользоваться FTP-клиентом CuteFTP (), но мы предпочитаем использовать файловую оболочку FAR. Две важные вещи, которые следует запомнить: первое — файлы шаблонов должны содержать имена, оканчивающиеся на .pl, и второе — они должны иметь право на выполнение (в UNIX-системах надо выполнить команду chmod 0755 имя_шаблона.pl).Это все!


Создание единого глобального электронного рынка - проект ebXML


© А.Календарев.

Оригинал статьи находится на сайте, посвященном проблеме использования электронных документов -



Создание галереи с помощью php.


,

Предлагаю вашему вниманию пример программирования на языке php с использованием баз данных mysql (в одном из вариантов программы) на примере создания галереи фотографий, картинок и т.п. Картинки в предпросмотре должны быть определенной ширины (чтобы не расползалась страница). Подобный вариант используется мной (2 вариант) и (1 вариант).

Галерея имеет следующие свойства:

предпросмотр; навигация "вперед-назад"; навигация по номерам страниц галереи; наличие описаний к картинкам; администрирование описаний к картинкам; варианты 2 и 3 имеют возможность изменять порядок вывода картинок; вариант 3 сделан с использованием базы mysql варианты 1 и 3 легко преобразуемы в галерею с возможностью дополнения галереи посетителями; если вы обнаружили еще какие-то свойства галереи, буду рад выслушать ваше мнение по адресу

Вариант 1

Программа ищет файлы картинок в указанном ей каталоге с маленькими картинками (предпросмотр). Затем она ищет описания для выводимых картинок в текстовом файле. Определяет кол-во картинок и создает навигацию по галерее. Определяет размеры картинок и выводит их с описаниями и с яваскриптом на каждой картинке, который открывает большой вариант картинки в новом окне с размерами на 40 пикселей больше размера картинки с возможностью скроллинга, если таковой окажется необходим для просмотра картинки полностью (при малом размере экрана).

Вот собственно и код варианта:

<html>

<head>

<TITLE>Photo-galery</TITLE>

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=Windows-1251">

<LINK REL=STYLESHEET TYPE="text/css" href="/style.css">

</head>

<body leftmargin=0 topmargin=0 marginwidth="0" marginheight="0">

<table width=650 cellspacing=0 cellpadding=5 border=0 cols=2><tr><td>

<div align="center">

<br>

<p align="center" class="zag-main">Картинная галерея.</p>



<?

// Пишем переменные, которые зависят от Вас

//

$scrpic=10; // максимальное кол-во фоток на

странице$big='../pic/big_regats/'; // путь к большим картинкам

$small='../pic/small_regats/'; // путь к малым картинкам

$ini=$DOCUMENT_ROOT.'/avrora/pic/read/read_regats.ini'; // путь к файлу с текстами к картинкам

//

//В данном случае, файл строится так: строка с названием картинки (без расширения файла)

//затем строка с подписью к картинке

//затем название следующей картинки и так далее.

//

//Например:

//1

//Моя первая фотография

//rt

//моя фотография rt.jpg

//.... и так до последней картинки. Если подписи к картинке нет, то надо оставлять пустую строку.

//

//

$kav="'"; // одинарные кавычки пригодятся нам потом в таком виде

// для отображения в браузере в яваскрипте. Там необходимо иметь оба вида кавычек,

// а для php надо еще поставить выводимое выражение в кавычки.

$podp='увеличить'; // надпись под картинкой,

// побуждающая клиента нажать на картинку для увеличения

//

$style_zag2='zag2-main'; // стили текста на странице

$style_osn='osn-main'; // стили текста на странице

$style_link='link'; // стили текста на странице

//

//

//сама программа

$text=file($ini); // читаем файл с подписями к картинкам в массив $text

$dir=$small; // указываем путь к каталогу малых фотографий

$handle=opendir($dir); // читаем заголовок каталога

$si=0; // счетчик файлов в папке

while ($file = readdir($handle)) { // читаем файл, пока не закончатся

if ($file!="..") { // исключаем из списка файлов "." и ".." (корень и верхний каталог).

$pic[$si]=$file; // присваиваем текущему элементу массива с именами файлов имя текущего файла

$si++; // плюсуем к счетчику файлов в папке 1

}

} // следующий файл

$maxpic=count($pic)-1; // сколько файлов в папке с малыми картинками

if ($begin=="") { // если на страницу зашли впервые, то $begin присваеваем 1

$begin=1;

}

$end=$begin+$scrpic-1; // $end - номер последней картинки на странице



if ($end>$maxpic) { // если последний номер на странице больше кол-во картинок в папке,

// то он равен последнему

$end=$maxpic;

}

$beginrew=$begin-$scrpic; // при переходе назад, начинаем показывать картинки с номера,

//равному "первый номер текущей страницы минус кол-во картинок на странице"

$beginfw=$begin+$scrpic; // при переходе вперед, начинаем показывать картинки с номера,

//равному "первый номер текущей страницы плюс кол-во картинок на странице"

$hrefrew='<a href='.$PHP_SELF.'?begin='.$beginrew.' class='.$style_zag2.'>назад</a>';

// создаем ссылку "назад"

$hreffw='<a href='.$PHP_SELF.'?begin='.$beginfw.' class='.$style_zag2.'>вперед</a>';

// создаем ссылку "вперед"

$navig=$hrefrew.' '.$hreffw; // ставим между ссылками "назад-вперед" символ ""

if ($beginrew<=0) { // если мы на первой странице, то ссылка назад не нужна

// $hrefrew='<a href='.$PHP_SELF.'?begin='.$beginrew.' class='.$style_zag2.'>назад</a>';

$navig=$hreffw;

}

if ($beginfw>$maxpic) { // если мы на последней странице, то ссылка вперед не нужна

// $hreffw='<a href='.$PHP_SELF.'?begin='.$beginfw.' class='.$style_zag2.'>вперед</a>';

$navig=$hrefrew;

}

// вывод на экран номеров страниц галереи

$scrmax=ceil($maxpic/$scrpic); // вычисляем, сколько страниц с картинками

for ($scr=1; $scr<=$scrmax; $scr++) { // начиная с первого номера до кол-ва страниц галереи

$beginsrc=($scr-1)*$scrpic+1; // вычисляем номер картинки,

// с которого будут выводиться картинки на странице

if ($beginsrc==$begin) { // если страница текущая,

// то ее номер выводим в виде простого текста, а не ссылки

echo '  <span class='.$style_zag2.'>'.$scr.'</span>  ';

}

else { // если страница не текущая, то выводим ссылку на нее и передаем параметры:

// номер картинки, с которой начать выводить на этой странице

echo ' <a href='.$PHP_SELF.'?begin='.$beginsrc.' class='.$style_zag2.'> '.$scr.' </a> ';



}

}

echo '<p align=center class='.$style_zag2.'>'.$navig.'</p>';

// вывод на экран навигации "вперед-назад"

for ($i=$begin; $i<=$end; $i++) { // начиная с первой картинки на странице,

// перебираем картинки вплоть до последней на странице

for ($j=0; $j<sizeof($text); $j++) { // читаем файл ини и собираем описания

$name_file=explode(".",$pic[$i]); //выделяем в названии файла его имя (без расширения)

if (trim($text[$j])==$name_file[0]) { // ищем название картинки,

// предварительно обрезав пробелы вокруг названия картинки в файле

// (если текущее название картинки $pic[$i] совпадает с проверяемым $text[$j])

$descript=trim($text[$j+1]);

// если картинка найдена, то в $descript пишем описание к картинке

}

else { // если название картинки не совпадает с искомым, то плюем на него

}

}

$photo=$big.$pic[$i];

// присваиваем $photo имя малого файла+путь к папке с большими картинками

$size=getimagesize($photo); // читаем информацию о картинке

$width=$size[0]+40; // получаем ширину картинки и + 40 (свободное поле вокруг картинки)

$height=$size[1]+40; // получаем высоту картинки и + 40 (свободное поле вокруг картинки)

$sxp=$size[2]; // получаем тип (расширение файла картинки)

$smphoto=$small.$pic[$i];

// присваиваем $smphoto имя малого файла+путь к папке с малыми картинками

$smsize=getimagesize($smphoto); // читаем информацию о картинке

$smwidth=$smsize[0]; // получаем ширину картинки

$smheight=$smsize[1]; // получаем высоту картинки

$smexp=$smsize[2]; // получаем тип (расширение файла картинки)

$winstat='toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=1,resizable=1,width='.$width.',height='.$height; // статус открываемого окна с большой картинкой

// выводим таблицу галереи.

// если номер картинки четный, то картинка слева, а описание справа и наоборот

// делаем это для неужасного внешнего вида галереи

// Вы можете разположить картинки как Вам заблагорассудится.

// итак:

?><table width=420 cellspacing=0 cellpadding=5 border=0 cols=2><tr><?



// выводим одинаковую часть кода таблицы дл ячейки картинки

//Далее выводим картинки в ячейках таблиц с описаниями. Делаем все с "предпросмотром"

//"предпросмотр предпочтителен, потому что не надо сразу грузить большие файлы,

//а клиент если захочет, сам загрузит то, что его заинтересовало в новых окнах.

//

if ($i/2==ceil($i/2)) { // если номер картинки на странице четный

echo '<td width=210 rowspan=2>

<p class='.$style_osn.'>'.$descript.'</p>

</td><td hight='.($smheight+2).'>

<table width=202 cellspacing=1 cellpadding=0 border=0 bgcolor="#000000" border=0><tr><td>

<a href='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');">

<img src='.$smphoto.' width='.$smwidth.' height='.$smheight.' border=0 alt="увеличить">

</a>

</td></tr></table>

</td></tr>

<tr><td valign=top>

<center>

<a href='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');" CLASS='.$style_link.'>'.$podp.'

</a>

</center>

</td></tr></table>';

}

else { // если номер картинки нечетный

echo '<td align=left><table width=202 cellspacing=1 cellpadding=0 border=0 bgcolor="#000000"><tr>

<td hight='.($smheight+2).'>

<a href='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');">

<IMG SRC='.$smphoto.' width='.$smwidth.' height='.$smheight.' border=0 alt="увеличить">

</a>

</td></tr></table>

</td>

<td width=210 rowspan=2>

<p align=left class='.$style_osn.'>'.$descript.'</p>

</td></tr>

<tr><td valign=top>

<center>

<a href='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');" CLASS='.$style_link.'>'.$podp.'



</a>

</center>

</td></tr></table>';

}

}

// вывод на экран "вперед-назад"

echo '<p align=center class='.$style_zag2.'>'.$navig.'</p>';

// вывод на экран номеров страниц

echo '<div align=center>';

for ($scr=1; $scr<=$scrmax; $scr++) {

$beginsrc=($scr-1)*$scrpic+1;

if ($beginsrc==$begin) {

echo '  <span class='.$style_zag2.'>'.$scr.'</span>  ';

}

else {

echo ' <a href='.$PHP_SELF.'?begin='.$beginsrc.' class='.$style_zag2.'> '.$scr.' </a> ';

}

}

?>

</div>

</td></tr></table>

</body>

</html>

Программа администрирования текстов описаний:

Была применена в моей статье . Я считаю этот способ самым проостым для начинающего программиста. Более сложный способ обновления я собираюсь сделать в будущих статьях.

Конечно, можно делать более серьезные интерфейсы, но в этом варианте, который конечно не рассчитан на ламера, можно быстро править сразу все позиции.

Вот собственно код:

<html>

<head>

<title>admin weather</title>

</head>

<body>

<?php

$adr=$DOCUMENT_ROOT."/avrora/pic/read/read_regats.ini"; // адрес файла, в котором и будут записываться названия файлов с описаниями

$password='pass'; // простенькая система авторизации

$eror='Password eror!';

$old=file($adr); // читаем то, что сейчас есть в файле

if ($submit) { // проверяем на нажатость кнопки

if ($pass==$password) {

$fp=fopen($adr,"w");

fwrite ($fp, $ini); // записываем в файл измененные данные

fclose($fp);

$old=file($adr);

}

else {

echo $eror;

}

}

?>

<form method=post action="<?php echo $PHP_SELF?>"> // информация, введенная в форму, обрабатывается этим же файлом

password:<input type=text name=pass><br>

inicialisation:<textarea name="ini" rows=15 cols=60>

<?

for ($i=0; $i<sizeof($old); $i++) {



echo $old[$i], ""; // выводим на экран текущий вариант файла

}

?>

</textarea>

<br>

<input type=submit name="submit" value="Enter">

</form>

</body>

</html>

В этом варианте, файл создаем так, как написано в комментарии к программе:

1

Моя первая фотография

rt

моя фотография rt.jpg

, где 1 и rt - имена файлов, а строки под ними соответственно описания к ним.

Вариант 2

Отличие этого варианта отпредыдущего в том, что:

Программа читает файл инициализации галереи.

В каждой строке такая конструкция (так надо заполнять файл для этого варианта!):

1.jpg|Моя первая фотография

rt.jpg|моя фотография rt.jpg

где символ "|" - это разделитель между описанием и именем файла картинки.

Как видно, в этом варианте надо писать в файле имя файла картинки с расширением. Если это вам это очень мешает, то можете переделать так, чтобы было в файле только имя, а расширение определялось бы автоматически, основываясь на первом примере.

Алгоритм такого варианта будет:
определитьимя картинки, считать имена файлов в папке с файлами, обрезая у имен файлов расширения, находим нужный, сравнивая каждый раз с тем, что взяли из файла. Именно совпавший и будет искомым.

Далее программа, создав массив из имен и описаний картинок, определяет, на какой странице галереи клиент находится и выводит ему соответственно ту или иную страницу.

Сам движок галереи остается тем же, как вы наверное заметили.

Изменяются некоторые его части.

Вот сам код:

<html>
<head>
<TITLE>Photo-galery</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=Windows-1251">
<LINK REL=STYLESHEET TYPE="text/css" href="/style.css">

</head>

<body leftmargin=0 topmargin=0 marginwidth="0" marginheight="0">

<table width=650 cellspacing=0 cellpadding=5 border=0 cols=2><tr><td>


<div align="center">

<br>

<p align="center" class="zag-main">Картинная галерея.</p>

<?
// Пишем переменные, которые зависят от Вас
//
$scrpic=10; // максимальное кол-во фоток на
странице$big='../pic/big_regats/'; // путь к большим картинкам
$small='../pic/small_regats/'; // путь к малым картинкам
$ini=$DOCUMENT_ROOT.'/avrora/pic/read/read_regats1.ini'; // путь к файлу с текстами к картинкам
//
//В данном случае, файл строится так: строка с названием картинки (без расширения файла)
//затем строка с подписью к картинке
//затем название следующей картинки и так далее.
//
//Например:
//1|Моя первая фотография
//rt|моя фотография rt.jpg
//.... и так до последней картинки. Если подписи к картинке нет, то надо оставлять пустую строку.
//
//
$kav="'"; // одинарные кавычки пригодятся нам потом в таком виде
// для отображения в браузере в яваскрипте. Там необходимо иметь оба вида кавычек,
// а для php надо еще поставить выводимое выражение в кавычки.
$podp='увеличить'; // надпись под картинкой,
// побуждающая клиента нажать на картинку для увеличения
//
$style_zag2='zag2-main'; // стили текста на странице
$style_osn='osn-main'; // стили текста на странице
$style_link='link'; // стили текста на странице
//
//
//сама программа

$text=file($ini); // читаем файл с подписями к картинкам в массив $text

for ($i=0; $si<sizeof($text); $i++) { // читаем файл ини и сохраняем имена картинок.
$si=$i+1;
$string=explode("|",$text[$i]);
$pic[$si]=$string[0]; // присваиваем текущему элементу массива с именами файлов имя текущего файла
$description[$si]=$string[1];
}

$maxpic=count($pic); // сколько файлов в папке с малыми картинками

if ($begin=="") { // если на страницу зашли впервые, то $begin присваеваем 1

$begin=1;
}$end=$begin+$scrpic-1; // $end - номер последней картинки на странице
if ($end>$maxpic) { // если последний номер на странице больше кол-во картинок в папке,
// то он равен последнему


$end=$maxpic;
}

$beginrew=$begin-$scrpic; // при переходе назад, начинаем показывать картинки с номера,
//равному "первый номер текущей страницы минус кол-во картинок на странице"
$beginfw=$begin+$scrpic; // при переходе вперед, начинаем показывать картинки с номера,
//равному "первый номер текущей страницы плюс кол-во картинок на странице"

$hrefrew='<a href='.$PHP_SELF.'?begin='.$beginrew.' class='.$style_zag2.'>назад</a>';
// создаем ссылку "назад"
$hreffw='<a href='.$PHP_SELF.'?begin='.$beginfw.' class='.$style_zag2.'>вперед</a>';
// создаем ссылку "вперед"
$navig=$hrefrew.' '.$hreffw; // ставим между ссылками "назад-вперед" символ ""
if ($beginrew<=0) { // если мы на первой странице, то ссылка назад не нужна

// $hrefrew='<a href='.$PHP_SELF.'?begin='.$beginrew.' class='.$style_zag2.'>назад</a>';

$navig=$hreffw;
}
if ($beginfw>$maxpic) { // если мы на последней странице, то ссылка вперед не нужна

// $hreffw='<a href='.$PHP_SELF.'?begin='.$beginfw.' class='.$style_zag2.'>вперед</a>';

$navig=$hrefrew;
}

// вывод на экран номеров страниц галереи

$scrmax=ceil($maxpic/$scrpic); // вычисляем, сколько страниц с картинками

for ($scr=1; $scr<=$scrmax; $scr++) { // начиная с первого номера до кол-ва страниц галереи
$beginsrc=($scr-1)*$scrpic+1; // вычисляем номер картинки,
// с которого будут выводиться картинки на странице
if ($beginsrc==$begin) { // если страница текущая,
// то ее номер выводим в виде простого текста, а не ссылки
echo '  <span class='.$style_zag2.'>'.$scr.'</span>  ';
}
else { // если страница не текущая, то выводим ссылку на нее и передаем параметры:
// номер картинки, с которой начать выводить на этой странице
echo ' <a href='.$PHP_SELF.'?begin='.$beginsrc.' class='.$style_zag2.'> '.$scr.' </a> ';
}
}

echo '<p align=center class='.$style_zag2.'>'.$navig.'</p>';


// вывод на экран навигации "вперед-назад"

for ($i=$begin; $i<=$end; $i++) { // начиная с первой картинки на странице,
// перебираем картинки вплоть до последней на странице

$descript=$description[$i];

$photo=$big.$pic[$i];
// присваиваем $photo имя малого файла+путь к папке с большими картинками
$size=getimagesize($photo); // читаем информацию о картинке
$width=$size[0]+40; // получаем ширину картинки и + 40 (свободное поле вокруг картинки)
$height=$size[1]+40; // получаем высоту картинки и + 40 (свободное поле вокруг картинки)
$sxp=$size[2]; // получаем тип (расширение файла картинки)

$smphoto=$small.$pic[$i];
// присваиваем $smphoto имя малого файла+путь к папке с малыми картинками
$smsize=getimagesize($smphoto); // читаем информацию о картинке
$smwidth=$smsize[0]; // получаем ширину картинки
$smheight=$smsize[1]; // получаем высоту картинки
$smexp=$smsize[2]; // получаем тип (расширение файла картинки)
$winstat='toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=1,resizable=1,width='.$width.',height='.$height; // статус открываемого окна с большой картинкой

// выводим таблицу галереи.
// если номер картинки четный, то картинка слева, а описание справа и наоборот
// делаем это для неужасного внешнего вида галереи
// Вы можете разположить картинки как Вам заблагорассудится.
// итак:
?><table width=420 cellspacing=0 cellpadding=5 border=0 cols=2><tr><?
// выводим одинаковую часть кода таблицы дл ячейки картинки

//Далее выводим картинки в ячейках таблиц с описаниями. Делаем все с "предпросмотром"
//"предпросмотр предпочтителен, потому что не надо сразу грузить большие файлы,
//а клиент если захочет, сам загрузит то, что его заинтересовало в новых окнах.
//
if ($i/2==ceil($i/2)) { // если номер картинки на странице четный
echo '<td width=210 rowspan=2><p CLASS='.$style_osn.'>'.$descript.'</p
></td><td hight='.($smheight+2).'><table width=202 cellspacing=1 cellpadding=0 border=0 bgcolor="#000000" border=0><tr><td><A HREF='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');">


<IMG SRC='.$smphoto.' WIDTH='.$smwidth.' HEIGHT='.$smheight.' BORDER=0 alt="увеличить"></A></td></tr></table
></td></tr><tr><td valign=top
><center><A HREF='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');" CLASS='.$style_link.'>'.$podp.'</a></center></td></tr></table>';
}
else { // если номер картинки нечетный
echo '<td align=left><table width=202 cellspacing=1 cellpadding=0 border=0 bgcolor="#000000"><tr><td hight='.($smheight+2).'><A HREF='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');"><IMG SRC='.$smphoto.' WIDTH='.$smwidth.' HEIGHT='.$smheight.' BORDER=0 alt="увеличить"></A></td></tr></table></td><td width=210 rowspan=2><p align=left CLASS='.$style_osn.'>'.$descript.'</p
></td></tr><tr><td valign=top
><center><A HREF='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');" CLASS='.$style_link.'>'.$podp.'</a></center></td></tr></table>';
}
}

// вывод на экран "вперед-назад"
echo '<p align=center class='.$style_zag2.'>'.$navig.'</p>';

// вывод на экран номеров страниц
echo '<div align=center>';
for ($scr=1; $scr<=$scrmax; $scr++) {
$beginsrc=($scr-1)*$scrpic+1;
if ($beginsrc==$begin) {
echo '  <span class='.$style_zag2.'>'.$scr.'</span>  ';
}
else {
echo ' <a href='.$PHP_SELF.'?begin='.$beginsrc.' class='.$style_zag2.'> '.$scr.' </a> ';
}
}

?>

</div>
</td></tr></table>

</body>
</html>

Программа администрирования та же, что и в варианте 1.



Вариант 3

В этом варианте используется база данных mysql вместо текстового файла для хранения описаний, имен картинок и порядка их следования.

Здесь тоже в базе хранятся именя файлов с расширениями (при варианте без расширений, будет тратиться время на пиоск картинки по описанному выше алгоритму, а при заливке картинок через вэбинтерфейс проще хранить имена файлов с расширениями).

Алгоритм работы программы такой же, что и в предыдущем примере. Однако, вместо считывания файла, считывается база галереи. Для ускорения можно было бы поместить операцию считывания в цикл вывода картинок на экран и не считывать все строки базы.

Для создания таблицы базы картинок используйте этот скрипт:

<?

//инициализация mysql:

$mysql_login='login';

$mysql_host='host';

$mysql_pass='password';

$mysql_db='db';

//

mysql_connect($mysql_host,$mysql_login,$mysql_pass);

mysql_select_db($mysql_db);

mysql_query("set CHARACTER SET cp1251_koi8") or die ("!--не могу записать"); // эта строка

используется, если сайт в кодировке win, а база в кодировке кои-8.

Если кодировки совпадают, строку надо закомментировать.

$query="CREATE TABLE galery_regats (numer tinyint(4) NOT NULL, name text NOT NULL, description text NOT NULL)";

$res=mysql_query($query) or die ("!--не могу создать таблицу");

header("location: admin.php"); // переход на страницу администрирования

?>

Программа администрирования:

<html>

<head>

<title>Admin galery</title>

<link rel=stylesheet type="text/css" href="/style.css">

</head>

<body bgcolor=#eeeeee>

<br>

<?

// логин/пароль

$log='total';

$pas='total';

//инициализация

mysql:

$mysql_login='login';

$mysql_host='host';

$mysql_pass='password';
$mysql_db='db';

//

$style_zag2='zag2-main'; // стили текста на странице

$style_osn='osn-main'; // стили текста на

странице$style_link='link'; // стили текста на странице



$kon_str="\n"; // конец строки

$razdel="|"; // разделитель между именем картинки и описанием

?>

<p align="center" class="<? echo $style_zag2; ?>">Картинная галерея.</p>

<?

mysql_connect($mysql_host,$mysql_login,$mysql_pass);

mysql_select_db($mysql_db);

mysql_query("set CHARACTER SET cp1251_koi8") or die ("!--не могу записать");

switch ($prov) { // проверяем состояние переменной $prov

case "edit":

// если пишем новый вариант базы:

if ($login!=$log $pass!=$pas) { echo "Введите правильно логин/пароль"; } // если пароль неверен

else {

// удаляем текущую базу картинок и создаем пустую таблицу

$query="DROP TABLE galery_regats"

$res=mysql_query($query) or die ("!--не могу удалить таблицу");

$query="CREATE TABLE galery_regats (numer tinyint(4) NOT NULL, name text NOT NULL, description text NOT NULL)";

$res=mysql_query($query) or die ("!--не могу создать таблицу");

$pics=explode($kon_str,$block); // бьем наш список по символу переноса строки

for ($i=0; $i<sizeof($pics); $i++) { // пишем в базу данные

$string=explode($razdel,$pics[$i]); // бьем строки по символу разделителя

$query="insert into galery_regats (number, name, description) values ('$i', '$string[0]', '$string[1]')";

mysql_query($query) or die ("!--не могу записать"); // пишем в таблицу

}

}

break;

default:

// если мы зашли не по нажатию на ентер:

// читаем базу картинок и сохраняем в массивы

$zapros="select * from galery_regats order by

numer";$res=mysql_query($zapros);

$kol=mysql_num_rows($res);

if ($kol==0) {

echo "<span class=$style_osn>Нет картинок в галерее.</span>";

}

for ($i=0; $i<$kol; $i++) { // читаем базу и сохраняем имена картинок.

$pic[$i]=mysql_result($res,$i,"name"); // присваиваем текущему элементу массива

$description[$i]=mysql_result($res,$i,"description");



}

break;

}

}

?>

<form method=post action="<? echo $PHP_SELF; ?>">

<textarea name="block" rows="40" cols="40">

<?

// выводим текущее состояние базы картинок

for ($i=0; $i<sizeof($pic); $i++) {

echo $pic[$i].$razdel.$description[$i].$kon_str;

}

?>

</textarea>

<input type="text" name="login" size="10">

<input type="text" name="pass" size="10">

<input type="hidden" name="prov"

value="edit"><input type="submit" name="enter" value="Enter">

</form>

</body>

</html>

Форма заполняется как и во втором варианте.

А для получения 3-го варианта в коде программы 2- го варианта строки от строки

//сама программа

до строки

$maxpic=count($pic); // сколько файлов в папке с малыми картинками

которые являются блоком считывания файла в массивы,

заменяются на блок:

mysql_connect($mysql_host,$mysql_login,$mysql_pass); // соединение с базой (коннект)

mysql_select_db($mysql_db); // выбор базы

mysql_query("set CHARACTER SET cp1251_koi8") or die ("-------------не могу записать");

// Если кодировки базы и сайта совпадают - закомментировать эту строку

$zapros="select * from galery_regats order by numer";

$res=mysql_query($zapros);

$kol=mysql_num_rows($res);

if ($kol==0) {

echo "Нет картинок в галерее.";

}

for ($i=0; $i

$si=$i+1;

$pic[$si]=mysql_result($res,$i,"name"); // присваиваем текущему элементу массива с именами файлов имя текущего файла

$description[$si]=mysql_result($res,$i,"description");

}

Результат работы блока точно такой же, что и во втором варианте - массивы $pic и $description, где храним имена файлов картинок и описания к ним. Но работает такая галерея быстрее. Однако, каждый раз, когда хотите залить новую картинку, надо администрить галерею, даже если не нужно описание.А в первом варианте стоит только лишь закинуть в папки файлы картинок.

Таким образом, получаем 3 рабочих варианта программы галереи. Если будут возникать вопросы по работе программы, адаптации под "свой сайт" или по принципам, пишите мне по адресу

Тотоев Александр



Создание и реструктуризация Web-сайтов


В двух предыдущих разделах обсуждались задачи, которые касались запросов, адресованных к существующим Web-сайтам и их содержанию. Однако, принимая во внимание тот факт, Web-сайты, по существу, обеспечивают доступ к сложным структурам информации, естественно применить методы систем баз данных для создания и поддержки Web-сайтов. Можно выделить два общих класса задач создания Web-сайтов: создание Web-сайтов из некоторой совокупности внутренних (underlying) источников данных и создание их путем реструктуризации существующих Web-сайтов. Как оказалось, для обоих этих классов задач необходимы одни и те же методы. Более того, заметим, что обеспечение Web-интерфейса для данных, которые содержатся в единственной системе базы данных [NS96], является простым частным случаем задачи создания Web-сайтов.4

Для того, чтобы стали понятными проблема создания Web-сайтов и возможность импорта для этой цели технологий баз данных, перечислим те задачи, которые должен решать создатель Web-сайта: (1) выбор тех данных, которые будут представлены на сайте и обеспечение доступа к ним, (2) проектирование структуры сайта, то есть, определение данных, содержащихся на каждой странице, и связей между страницами, и (3) проектирование графического представления страниц. В существующих инструментальных средствах управления Web-сайтами эти задачи, по большей части, взаимозависимы. При отсутствии каких-либо инструментальных средств создания сайта, разработчик вручную пишет содержимое HTML-файлов или пишет программы для их продуцирования. Одновременно он должен сосредоточить свое внимание на содержании страницы, ее связях с другими страницами, а также на ее графическом представлении. В результате, весьма утомительным становится решение нескольких других важных задач, таких как автоматическое обновление сайта, реструктуризация сайта или спецификация ограничений целостности, налагаемых на структуру сайта.

Web-сайты как декларативно определенные структуры: С целью применения технологий баз данных для создания Web-сайтов было разработано несколько систем [FFK+98, AMM98, AM98, CDSS98, PF98, JB97, LSB+98, TN98].


Общая характерное свойство этих систем состоит в том, что они обеспечивают явное декларативное представление структуры Web-сайта. Структура Web-сайта рассматривается как представление, определенное над существующими данными. Однако, следует подчеркнуть, что языки, используемые для создания этих представлений, дают в результате графы Web-страниц с гипертекстовыми связями, а не простые таблицы. Указанные выше системы различаются моделями данных, которую они используют, языками запросов, а также использованием или отказом от использования промежуточного логического представления Web-сайта наряду с наличием конечного представления в формате HTML.

Создание Web-сайта, использующего декларативное представление его структуры, обеспечивает несколько важных преимуществ. Так как структура и содержание Web-сайта определяются декларативно по запросу, а не процедурным образом с помощью программы, достаточно просто могут создаваться множественные версии такого сайта. Например, возможно легко построить внутренние и внешние представления сайта организации или создать сайты, предназначенные для различных классов пользователей. В настоящее время создание множественных версий требует написания многочисленных наборов программ или создания вручную различных наборов HTML-файлов. Создание множественных версий сайта может быть осуществлено либо написанием различных запросов, специфицирующих определения версий сайта, либо путем изменения графического представления независимо от внутренней структуры. Кроме того, декларативное представление структуры Web-сайта также позволяет легко поддерживать эволюцию этой структуры. Например, чтобы реорганизовать страницы, основанные на часто используемых шаблонах [PE97], или расширить содержание сайта, просто переписывают запрос, специфицирующий определение сайта, а не перерабатывают набор программ или HTML-файлов. Декларативная спецификация Web-сайтов обладает и другими достоинствами. Например, появляется возможность формулировать и налагать на сайт ограничения целостности [FFLS98], осуществлять обновление сайта фрагментарно, когда происходят изменения внутренних данных.


Помимо этого, декларативная спецификация обеспечивает платформу для разработки алгоритмов оптимизации управления Web-сайтом с интенсивной обработкой данных на стадии исполнения. Актуальной проблемой управления Web-сайтом на стадии исполнения является автоматический поиск оптимального компромисса между предварительной обработкой частей Web-сайта и обработкой непосредственно при обращении. Отметим, наконец, что создание Web-сайтов, использующих эту парадигму, также облегчит решение задач обработки запросов к Web-сайтам и интеграции данных из множественных Web-источников.



Архитектура прототипа системы с декларативно определенной структурой показана на рис. 3. На нижнем уровне системы осуществляется доступ к множеству источников данных, содержащих те данные, которые будут обслуживаться на Web-сайте. Эти данные могут храниться в базах данных, в структурированных файлах, или на уже существующих Web-сайтах. Данные представляются в системе средствами некоторой модели данных, и система обеспечивает унифицированный интерфейс к этим источникам данных, используя технологии, подобные описанным в предыдущем разделе. Главным шагом в создании Web-сайта является спецификация выражения, которое в декларативной форме представляет структуру Web-сайта. Это выражение записывается на специальном языке запросов, предоставляемом системой. В результате применения этого запроса к внутренним данным формируется логическое представление Web-сайта в терминах модели данных системы (например, как помеченный ориентированный граф). Наконец, для фактического создания доступного для просмотра Web-сайта система содержит метод (например, HTML-шаблоны) для трансляции специфицированной логической структуры в набор HTML-файлов.

Рассмотрим теперь кратко наиболее важные характеристики различных систем. Система STRUDEL [FFK+98] использует в качестве модели слабоструктурированных данных помеченные ориентированные графы для моделирования как внутренних данных, так и Web-сайта. В этой системе используется единственный язык запросов STRUQL, служащий и для интеграции исходных данных и для определения структуры Web-сайта.


Система ARANEUS [AMM97b] использует более структурированную модель данных ADM и предоставляет язык для преобразования данных в ADM, а также язык для создания Web-сайта из данных, моделируемых средствами ADM. Кроме того, ARANEUS использует в этой модели данных специфические для Web конструкции. Система Autoweb [PF98] основана на модели проектирования гипермедийной среды (Hypermedia Design Model, HDM) - инструментальном средстве для разработки гипермедийных приложений. Модель данных этой системы базируется на модели "сущность-связь". "Схема доступа" определяет, как осуществлять навигацию и доступ к гипербазе на просматриваемом сайте. "Схема представления" определяет, каким образом представляются объекты и пути в гипербазе и схемах доступа. Во всех трех упомянутых выше системах обеспечивается строгое разделение между стадиями создания логической структуры Web-сайта и спецификации графического представления сайта. Система YAT [CDSS98] демонстрирует применение языка конвертирования данных к решению проблемы создания Web-сайта. При использовании YAT, проектировщик Web-сайта записывает множество правил преобразования исходных данных в дерево абстрактного синтаксиса, представляющее результирующие данные в формате HTML, опуская фазу промежуточного логического представления. Фактически, другие языки для конвертирования данных (например, [MZ98, MPP+93, PMSL94]) могут подобным же образом использоваться для создания Web-сайта. Система WIRM [JB97] аналогична указанным выше системам в том смысле, что она дает пользователям возможность строить Web-сайты, в которых страницы могут рассматриваться как чувствительные к контексту представления внутренних данных. Главное назначение WIRM состоит в интеграции данных медицинских исследований в рамках национального проекта по изучению мозга человека.


Создание индекса для сайта


Автор: Randal L. Schwartz
Перевод Анисимова Михаила ()

Вы, может, знаете, что HTML разрешает вставлять META-тэги в заголовок документа. Тогда вы, я просто уверен, знаете для чего они нужны. Кто не в курсе - кратенько поясню: Существуют поисковые сервера, которые ползают по зарегистрировавшимся в их базе сайтах и индексируют странички. При этом они обращают пристальное внимание на МЕТА-тэги, а особенно на keywords и description (<ключевые слова> и <описание>).

Синтаксис этих двух МЕТА-тэгов выглядит так:

<meta name=description content="CGI&Perl - Документация и скрипты"> <meta name=keywords content="perl cgi documentation scripts скрипты документация перл">

Ключевые слова также могут быть разделены запятой.

Ну а теперь непосредственно о скрипте. Скрипт осматривает все странички сайта на предмет meta description и meta keywords и составляет итоговую таблицу - индекс, или предметный указатель.

Строки 1-3: Обычное начало программы.

5-26: Часть скрипта, которую нужно сконфигурировать под свои нужды.

7: Список URLов, которые необходимо проиндексировать. Но если все страницы сайта связаны гиперссылками - то необходима лишь один URL.

9-24: Определение процедуры OK_TO_FOLLOW. Принимает URI-объект (http), возвращает единицу, если эту ссылку надо сканировать и нуль, если не надо.

11-13: Необходимо, чтобы скрипт не выходил за пределы сайта.

14-16: Не нужно также запускать никакие CGI-скрипты

17-22: Убираем из процесса индексации картинки и другие не-HTML файлы.

Отметьте небольшую хитрость: цикл for здесь вовсе не цикл, он нужен лишь для того, чтобы переменная $_ равнялась тому, что внутри скобок for ()

23: Передано то, что необходимо проиндексировать - вернем единицу.

28-31: Подключаем модули: CGI::Pretty - стандартный, LWP::UserAgent, HTML:Entities, WWW::Robot - входят в библиотеку LWP.

33-35: Определение глобальных переменных. %description - хэш, ключами которого являются URLы, а значениями - описания (meta description). %keywords - URL- >ключевые слова (keywords). %keywords_caps содержит регистр (верхний или нижний) написания ключевого слова.




37-45: Настройки индексатора. За подробностями обратитесь к документации по WWW::Robot. Здесь же устанавливаем, что индексатор идентифицирует себя как MetaBot, версии 0.15, ну и e-mail адрес. USERAGENT - будет LWP::UserAgent, отключена проверка MIME-типов.

47: Включает проверку конфигурации прокси-сервера, вобщем-то это и не нужно. 49-54: Одна из двух callback-функций, которую вызывает WWW::Robot. Как только найден URL, вызывается follow-url-test callback. Здесь вызываем функцию OK_TO_FOLLOW, чтобы отсеять лишнее.

55-76: Вытаскиваем информацию с каждой странички.

58-61: Нам нужны только keywords и description

63-67: Сохраним описание, предварительно очистив его от переносов строк и символов табуляции, заменив их на пробелы.

68-75: Запомним ключевые слова и их регистр. В данном скрипте предполагается, что слова разделены запятыми. Можно разделителями сделать пробелы, заменив split(/,/,... на split (/ /, ... Или и пробелы и запятые - split (/[, ]/,...

77: Запуск индексации. Для большого сайта займет довольно длительное время.

В строке 81 содержится оператор print, который продолжается до конца скрипта и выводит таблицу-индекс.

79: хэш %seen_letter нужен для того чтобы вверху странички выдать ссылки в виде букв алфавита, например: <Jump to: A B K L P R S W Z>

Для каждого ключевого слова выдается ссылка на документ, где оно встречается и описание из этого документа (3 колонки в таблице).

Вот и все.


Создание news-reader'а с веб-интерфейсом.


Перевод Анисимова Михаила ()

Каждый, кто начинает программировать на Перле, сталкивается с аббревиатурой CPAN, что значит Comprehensive Perl Archive Network ("всеобъемлющий архив по Перлу") CPAN - прекрасный ресурс, где можно отыскать все что угодно, связанное с Перлом. В мире много зеркал CPAN, так что выбирайте то, которое вам ближе географически. Для этого сходите на ftp://ftp.funet.fi/pub/languages/perl/CPAN/CPAN, где есть список всех зеркал.

Немного об организации архива. Каждое зеркало центрального сервера содержит файл CPAN/Roadmap или CPAN/Roadmap.html, а также CPAN/modules/Readme, где есть описания всех содержащихся модулей. Вы скажете - Зачем нам эти модули? Мы и сами можем написать... Ну если так - то пожалуйста, пишите сами. А те, кто желает сэкономить время и силы, зайдите на CPAN и найдите для себя уже готовый модуль.

Не так давно передо мной стала задача - сделать что-то наподобие news-reader'а прямо на веб-странице. То есть: при обращении к серверу пользователь получает список сообщений в группе новостей (конференции) в виде ссылок на сами сообщения. Щелкнув по ссылке, пользователь сможет поглядеть картинку, содержащуюся в сообщении. Доступ к конференции осуществляется по протоколу NNTP.

Мне нужен был CGI, NNTP и base64 для декодирования картинок внутри сообщений. Для обеспечения CGI-интерфейса был взят модуль CGI.pm (CPAN/authors/id/LDS/CGI.pm-2.13.tar.gz). Для того, чтобы общаться с news-сервером по NNTP протоколу я нашел NNTPClient все там же на CPAN - CPAN/authors/id/RVA/NNTPClient-0.22.pm.gz. Ну и последний компонент - base64 декодировщик я нашел в модуле LWP (MIME:Base64) (CPAN/authors/id/LDS/CGI-modules-2.74.tar.gz.)

Использование библиотек, написанных не мной самим, позволило отвлечься от низкоуровневых задач, и сконцентрироваться на самом высоком уровне функционирования скрипта. Да и время сэкономило немало.

Вот такой скрипт получился в результате:



Создание нового пресс-релиза


Расширим функциональность нашей системы, добавив возможность создания новых пресс-релизов, без необходимости непосредственной работы с базой данных для пополнения таблицы tbl_news_items новой информацией.

Итак, новая Perl-программа (которая, как и предыдущие две, находится на компакт-диске) будет отличаться от предыдущих прежде всего тем, что предназначена не для отображения данных, а для их добавления в БД. Следовательно, мы должны несколько изменить часть, отвечающую за взаимодействие с БД, применив SQL-запрос INSERT и соответствующие ему операторы модуля DBI.

Строки 12-18 — это тело основной программы:

12. if ($cmd ne "add") { 13. &show_form; 14. } else { 15. $dbh = DBI->connect(‘dbi:mysql:db_website’, _ ’root’,’’); 16. &add_pr; 17. dbh->disconnect; 18. }

Здесь мы проверяем, поступила ли команда на добавление пресс-релиза в базу данных. Как только она поступила, устанавливаем соединение с БД (15), выполняем подпрограмму app_pr() (16) и завершаем соединение (17). Если же команды не было, то просто отображаем форму заполнения (13) для данных пресс-релиза — процедура show_form().

Строки 20-36 — это тело процедуры добавления пресс-релиза pr_add():

19. 20. sub add_pr { 21. $title = $q->param("pr_title"); 22. $author = $q->param("pr_author"); 23. $body = $q->param("pr_body"); 24. $body =~ s/\r\n/<br>/g; 25. 26. my($sql) = "INSERT INTO tbl_news_items (col_title,col_author,col_body,col_date) VALUES (\’$title\’,\’$author\’,\’$body\’,CURDATE())"; 27. $rs = $dbh->do($sql); 28. 29. if ($@) { 30. $rc = $dbh->rollback; 31. } else { 32. $rc = $dbh->commit; 33. } 34. 35. print "Location: /cgi-bin/pr-list-dbi.pl\n\n"; 36. }

Сперва обрабатываем данные формы (22-25), составляем SQL-запрос (27) и выполняем его (27) с помощью DBI-метода $dbh->do(). Поскольку здесь производится процедура вставки данных в БД, то нужно позаботиться о возможности отмены операции в случае сбоев. Для этого мы вставили код отмены транзакции и отката в предыдущее состояние (30-34). При сбое при выполнении $dbh->do() отменяем сделанные изменения (31). Если же сбоя не произошло, то подтверждаем сделанные изменения (33). Далее после всех действий просто переходим на страницу со списком всех пресс-релизов (36).

Строки 37-55 — это тело процедуры вывода формы для ввода информации о новом пресс-релизе (используется HTML-шаблон, имя которого задано в переменной $TPL_INSERT, pr-add-tpl.htm): 37. 38. sub show_form { 39. print "Content-type:text/html\n\n"; 40. 41. open (L, "$TPL_INSERT"); 42. while ($line=<L>) { 43. chomp($line); 44. if ($line=~/\@/) { 45. if ($line=~/\@ADD\@/) { 46. $toadd = "pr-add-dbi.pl"; 47. $line =~ s/\@ADD\@/$toadd/; 48. } else { 49. $tolist = "pr-list-dbi.pl"; 50. $line =~ s/\@LIST\@/$tolist/; 51. } 52. } 53. print "$line\n"; 54. } 55. close(L);



Спец-ориентированные Java-приложения


2.1 RMI-приложения

Вызов удаленных методов (RMI - Remote Method Invocation) обеспечивает средства коммуникации между Java программами, даже если они выполняются на разных компьютерах, находящихся в противоположных точках земного шара.

Важная особенность RMI заключается в том, что он представляет программируемый интерфейс для работы с сетями в отличие от сокетов TCP. Главное преимущество его в том, что он предлагает вам интерфейс более высокого уровеня, основанный на вызовах методов, так, как если бы удаленный объект обрабатывался локально. RMI более удобен и более естественен, чем интерфейс, основанный на сокетах, но он требует выполнения Java-программ на обоих концах соединения. Сетевое соединение, тем не менеее, достигается использованием все того же TCP/IP протокола.

Рассмотрим основные шаги для построения работающего RMI-приложения:

Разработка удаленных объектов и кодов для сервера и клиента Java-компиляция RMI-компиляция Перемещение .class-файлов в соответствующие директории Регистрация Старт сервера Старт клиента

Следующий ниже пример разработан для клиента и сервера, выполняющихся на одной и той же машине, однако, заложенные здесь принципы можно с успехом применить для программ, выполняющихся на разных машинах и даже с различной архитектурой. Программа клиента ищет имена и номера телефонов в центральной базе, постоянно резидентной на сервере.

Как работает RMI

Вы определяете Java-интерфейс, чтобы описать каждый объект, который будет дистанционно разделяем, и перечисляeте общие методы, которые могут быть вызваны для объекта. Сервер будет использовать RMI-интерфейс и создаст объекты для вызова, специальным образом зарегистрированные и доступные для вызова по URL-основанной схеме, например: rmi://localhost/LookupServer

Клиент, используя эту запись, будет пытаться отыскать объект с данным именем, и получить удаленную ссылку к нему. Затем вызванный метод будет обработан с помощью RMI компилятора и преобразован из пользовательского кода в последовательную форму объекта, который передается пользователю с помощью TCP/IP.




Разработка удаленного объектного кода

RMI поддерживает объекты Java, осуществляющие связь через их методы, независимо от того, где эти объекты размещены. Первый шаг для создания класса, к которому можно обратиться дистанционно, - это определение интерфейса, описывающего методы, которые являются дистанционно-разделяемыми. // Lookup.java import java.rmi.*; public interface Lookup extends Remote { public String findInfo(String info) throws RemoteException; }

Java.rmi.Remote - пустой интерфейс, который указывает, что это удаленный объект, - так объекты класса, выполняющие Поиск(_Lookup_) отмечены удаленными ссылками. Все методы в удаленном интерфейсе должны быть объявлены через исключение типа Java.rmi.RemoteException, которое активизируется всякий раз, когда метод удаленного вызова дает сбои.

Разработка серверного кода

После того как вы определили интерфейс к удаленному объекту, нужно выполнить следующий шаг - разработать код сервера. Сервер осуществляет объектный интерфейс и создает образцы объекта, который будет дистанционно-разделяем.

Для нашего примера это будет выглядеть следующим образом:

// LookupServer.java import java.io.*; import java.util.*; import java.rmi.*; import java.rmi.server.*; public class LookupServer extends UnicastRemoteObject implements Lookup { private Vector save = new Vector(); public LookupServer(String db) throws RemoteException { try { FileReader fr = new FileReader(db); BufferedReader br = new BufferedReader(fr); String s = null; while ((s = br.readLine()) != null) save.addElement(s); fr.close(); } catch (Throwable e) { System.err.println(_exception_); System.exit(1); } } public String findInfo(String info) { if (info == null) return null; info = info.toLowerCase(); int n = save.size(); for (int i = 0; i < n; i++) { String dbs = (String)save.elementAt(i); if (dbs.toLowerCase().indexOf(info) != -1) return dbs; } return null; } public static void main(String args[]) { try { RMISecurityManager security = new RMISecurityManager(); System.setSecurityManager(security); String db = args[0]; LookupServer server = new LookupServer(db); Naming.rebind(_LookupServer_, server); System.err.println(_LookupServer ready..._); } catch (Throwable e) { System.err.println(_exception: _ + e); System.exit(1); } } }



Сервер читает в текстовой базе номера телефонов и имена и сохраняет их внутренне. Метод findInfo ищет затем нужное имя и телефон.

Пример базы данных:

Ivanov, Ivan 295-0083

Petrov, Peter 775-9958

Romanov, Alexander 555-7779

Заметим, что LookupServer является расширением стандартного класса java.rmi.server.UnicastRemoteObject и выполняет Lookup. Один из этих классов обеспечивает некоторые базисные реквизиты, необходимые для удаленных объектов, а другой определяет методы, которые будут вызваны дистанционно.

Установка службы безопасности

Наиболее сложная часть этого кода - то, что происходит в процедуре main(). Первым делом нужно установить защиту. RMI принужден загружать удаленные .class файлы и в этом смысле напоминает какой-нибудь web-браузер с его операциями по загрузке апплетов, что само по себе всегда небезопасно. Если вы не установили защиту, то по умолчанию должны загружаться только локальные файлы, и RMI по определению не может работать с такими ограничениями. Так что вы должны установить security manager, чтобы сделать возможной загрузку удаленных .class файлов.

Образец LookupServer затем регистрируется с помощью службы Naming.rebind и становится доступным клиенту по имени.

Вы могли бы задаться вопросом, как удаленный метод фактически становится вызываемым, если сервер не содержит никакого сетевого кода и никаких TCP/IP примитивов? Это происходит за сценой, поскольку сервер и клиент используют так называемые скелетоны и стабы для коммуникации между собой. Соответствующие .class файлы генерируются из серверного .class файла через RMI транслятор, описанный ниже.

Концептуально, класс stub(заглушка) выглядит так:

public class LookupServer_Stub extends java.rmi.server.RemoteStub implements Lookup, java.rmi.Remote { ... }

и скелетон - так: public class LookupServer_Skel implements java.rmi.server.Skeleton { ... }

Использование команды: Javap -c LookupServer_Stub

будет показывать байт-код и иллюстрировать то, что происходит за сценой.

Стаб(stub) -это суррогат для удаленного объекта, и скелетон - некая сущность на сервере, которая обрабатывает удаленные вызовы.



Стаб обеспечивает функции приема передачи на стороне клиента, а скелетон - на стороне сервера. При этом производится преобразование объектов в последовательную форму, а проще говоря, в поток байтов, передаваемых с помощью протокола TCP/IP

Разработка клиентского кода // LookupClient.java import java.rmi.*; import java.rmi.server.*; public class LookupClient { public static void main(String args[]) { try { RMISecurityManager security = new RMISecurityManager(); System.setSecurityManager(security); String host = _localhost_; String server = _LookupServer_; String name = _rmi://_ + host + _/_ + server; Lookup look_obj = (Lookup)Naming.lookup(name); String results = look_obj.findInfo(args[0]); if (results == null) System.err.println(_** not found **_); else System.out.println(results); } catch (Throwable e) { System.err.println(_exception: _ + e); System.exit(1); } } }

Если вы активизируете сервер, выполняя прямой клиентский запрос, то защита для пользователя определяется такая же как и на сервере. URL при этом определяется как: Rmi://localhost/LookupServer

где localhost - имя локального компьютера (IP, адрес = 127.0.0.1), используемого как сервер. Клиент располагается на той же самой машине. Вы можете также использовать и удаленную главную ЭВМ. Когда вызов к нужному методу сделан, результаты незамедлительно передаются клиенту.

Компиляция кода

Три файла - Lookup.java, LookupServer.java, и LookupClient.java компилируются как и обычно в Java: javac Lookup.java javac LookupServer.java javac LookupClient.java

Выполнение RMI компилятора

После того, как вы откомпилируете эти файлы, выполните RMI Compiler (rmic): rmic LookupServer

чтобы получить LookupServer_Skel.class и LookupServer_Stub.class файлы. Вы должны переместить клиентские файлы (Lookup.class, LookupClient.class, и LookupServer_Stub.class) в директорию, откуда вы их желаете выполнять как клиент.

Вы должны переместить серверные файлы (Lookup.class, LookupServer.class, LookupServer_Skel.class, и LookupServer_Stub.class) в директорию, где они станут доступными для публичного доступа.



Регистрация

Объект, к которому обращаются дистанционно, должен быть введен в регистр объектов, т.е. зарегистрирован. В JDK 1.1 имеется специальная программа

Rmiregistry

Rmiregistry может выполняться или в отдельном окне или как фоновый процесс на сервере.

Старт сервера

Вы должны стартовать сервер по команде: java LookupServer database_name

К примеру, если ваша база данных с набором имен и телефонов находится в файле C:\PHONE.TXT, то вы должны дать команду: java LookupServer C:\PHONE.TXT

Старт клиента

Клиентская программа стартуется по команде: java LookupClient Ivanov

_Ivanov_ - это искомое имя в базе.

Таким образом, RMI дает возможность создавать распределенные Java-to-Java прикладные программы, в которых методы удаленных объектов Java вызываются из других Java-программ на различных главных ЭВМ так как, если бы эти методы вызывались локально. Естественно, что подобные возможности можно эффективно использовать при работе с SQL-серверами, которые предоставляют Java-API интерфейс для доступа к данным. Например, в группе продуктов Informix в Informix Client SDK дано описание Informix Object Interface for Java, где приводятся многочисленные примеры, как организовать взаимодействующие RMI-приложения с доступом к базам данных Informix. Более того, имеется и соответствующий RMI-сервер, который содержит массу удобных и полезных методов, которые можно вызывать дистанционно. В сущности, приведенный выше пример можно приспособить для работы с любыми базами данных и SQL-серверами, если вы знаете каким образом устроен Java-API интерфейс для доступа к базам данных. В крайнем случае не возбраняется и использование JDBC в RMI-приложениях, хотя вряд ли это будет в достаточной степени эффективно. В Informix, например, для непосредственного взаимодействия с базами данных существуют два RMI-пакета: informix.api.remote.rmi - для удаленных клиентов и informix.api.remote.rmi.server - для rmi-сервера. При этом в клиентском приложении используется интерфейс к DBMSManager, который накапливает информацию обо всех серверах Informix и базах данных, и вы можете установить либо локальное, либо удаленное соединение с базой через RMI сервер.Для локального соединения создается DirectDBMSManager объект. Для удаленного соединения создается RMIDBMS-Manager объект и передается к соответствующему RMI серверу. Спецификация RMI сервера осуществляется в форме: rmi://hostname[:port]/ //Создание DBMSManager объекта DBMSManager getDBMSManager() throws Exception { // based on RMI Checkbox, get appropriate DBMSManager DBMSManager dbmsManager; if (RMIcheckbox.getState()) dbmsManager = new RMIDBMSManager(rmiServerTextField.getText()); else dbmsManager = new DirectDBMSManager(); return dbmsManager;

Само взаимодействие с базой осуществляется с помощью специальных транзакционных методов и методов управления курсором, которые могут вызываться как локально, так и дистанционно. В различных базах и SQL-серверах это может осуществляться по разному, но если сервер кроссплатформенный - единый и универсальный Java-API интерфейс играет немаловажную роль.


Статьи по web-дизайну


Mike Melnikov ()

Ниже приведены некоторые статьи, написанные мною с целью помочь начинающим WEB-дизайнерам. Статьи основаны на информации, распыленной в различных источниках (начиная с книг и кончая Internet, или наоборот :), а также на личном опыте.

- некоторые общие размышления, которые, тем не менее, имеют под собой твердую почву.

- для того, чтобы начать творить, нужно иметь хороший и надежный инструмент.

- хороший инструмент иметь мало - нужно его еще и освоить.

- самый первый вопрос, который можно предъявить web-сайту - для чего ты, собственно, нужен?

- почему на одни странички ходить приятно, а с других хочется уйти почти сразу?

- провожают по уму, а встречают - все же по одежке. Её величество Графика :-)

- у Вас есть красивая фотография, а если она еще и быстро пересылается, то и все остальные смогут ее оценить.

- у Вас есть красивая фотография в формате GIF ;), а если она еще и быстро пересылается, то и все остальные смогут ее оценить.

- как это влияет на нас и наших посетителей? И почему некоторым из них не нравится Ваш дизайн (как одна из возможных причин :)?

- как сделать так, чтобы посетители Ваших страничек могли отправить Вам сообщение? Краткое руководство по созданию формы на Вашей страничке и ее отсылки по почте с использованием готового CGI-скрипта.

- краткое и понятное объяснение о применении включений на стороне сервера и получаемых от этого преимуществ.

- нет-нет, это не комедия Карло Гольдони, и Труффальдино здесь ни при чем. Это... несчастный web-дизайнер, прилагающий массу усилий, чтобы угодить и приверженцам Microsoft Internet Explorer, и приверженцам Netscape Navigator.

- продолжаем наш практикум по написанию совместимых страничек. И на этот раз остановимся на правилах, применение которых позволяет резко уменьшить количество проблем с совместимостью.

- таблицы, как основное средство верстки сложного дизайна, и особенности их использования при создании совместимых страничек. - а теперь разберемся как и для чего разрезают картинки и зачем помещают их в таблицы. - невидимые таблицы - очень мощное средство.


Правильное их применение позволяет получать эффекты, другими способами довольно трудно достижимые. - Давайте-ка займемся сегодня оформлением таблиц. Вам наверняка не нравится, как оформлены таблицы по умолчанию. То, что называется рамкой, практически никогда не вписывается дизайн. А их псевдотрехмерность просто ужасна! - Итак, Вы сделали первую версию своего сайта и даже вывесили его в Internet, но через некоторое время Вы заметите, что на него практически никто не ходит, за исключением Вас и изредка Ваших друзей. - Если Вы еще не догадались, то я имею в виду META-теги. Их роль не заметна при отображении странички. Это лишь команды для web-сервера или броузера, но команды важные. - Кто об этом все знает, тот может пропустить эту статью, остальным же я поведаю о причинах возникновения различных кодировок и проблемах web-дизайна, связанных с ними. - Знание некоторых принципов возмещает незнание многих фактов. Сегодня мы поговорим о технологии сжатия JPEG и о том, за счет чего достигаются столь сильные степени сжатия. - Скриптовые языки в некотором роде перевернули мир, и именно благодаря им появился DHTML, который позволяет делать со страничкой практически что угодно. - Продолжаем разговор о применении скриптов на web-страничках. И начнем мы, пожалуй, с написания некоторых функций, которые нам впоследствии очень пригодятся. - Несколько небольших и полезных Java-скриптов позволяющих добавить к функциональности сайта некоторые приятные мелочи. - С этой статьи мы начнем разбираться с более сложными и функционально-законченными скриптами. И начнем с написания универсальной функции проверки формы перед отсылкой на сервер. - Для чего применяются фреймы? Как правильно с ними работать? Когда их лучше избегать и какие подводные камни могут подстерегать нас на этом пути? - Сегодня мы разберемся с тем, как организовать на страничке локальную баннерную систему, пользуясь только средствами JavaScript. - Как лучше всего организовать работу по созданию сайта? Чему следует уделить больше внимания? И с чего же все-таки следует начать? - Эффект, который мы сейчас рассмотрим, является, пожалуй, самым распространенным.И заключается он в смене изображения при наведении на него мышкой. Часто можно слышать английское название эффекта - RollOver, что обычно переводят как "перекатывание". - Немного специфическая статья и посвящена она решению проблем, возникающих при использовании на сайте фреймов. И, в частности, проблеме индексации таких сайтов поисковыми роботами и формированию фреймовой структуры при обращении к одной из внутренних страничек. - Поговорим о каскадных таблицах стилей. Их применение позволяет перейти на новый уровень создания сайтов и добиваться нужных эффектов оформления более простыми и логичными способами. - Продолжаем разговор о применении таблиц стилей. Сначала разберемся с каскадностью стилей, а потом перейдем к рассмотрению синтаксиса и обзору наиболее часто встречающихся параметров, применяемых при создании стилей.


Строительство приложений с помощью WML.


WML был разработан для для устройств с низкой пропускной способностью и маленьким дисплеем. В качестве составной этого дизайна была применена концепция дек и карт. Один WML-документ (а точнее элементы, содержащиеся внутри элемента <wml>) называется декой (deck). Интерактивное взаимодействие с пользователем осуществляется с помощью карт (card). Достоинство такой реализации заключается в том, что несколько экранов могут быть загружены на клиентское устройство за один раз. Используя WMLScript, обработка действий пользователя может быть произведена с использованием находящихся в одной деке карт, исключая тем самым множественные транзакции с сервером. Конечно, в связи с ограниченными ресурсами клиентского устройства возникает другая проблема. Поэтому вам вполне возможно придется разбрасывать ваши карты по разным деками во избежании чрезмерного увеличения объема одного файла.



Структура


Элемент

Access

Атрибуты:

domain - имя домена для запрета доступа. Микроброузер будет просматривать и сравнивать со значением этого атрибута все имена доменов встречающиеся в документе. Так если "<access domain="motorola.com"/>" броузер сможет зайти на "http://www.motorola.com/", но не сможет зайти на "http://www.rola.com/" или на "http://www.motorola.net/".

path - путь для сравнения. Работает примерно так же как и атрибут домен. Так если "<access path="/internal"/>" путь "/internal/wml" пройдет проверку, в то время как "/internal-wml" - нет.

Элемент "access" с примерно такими атрибутами: "<access domain="motorola.com" path="/spin"/>" разрешит ссылку на деку только со следующих адресов:

http://www.motorola.com/spin/getuid.cgi

https://www.motorola.com/spin/index.wml

http://www.motorola.com/spin/madk/create_index.cgi?x=123&y=234

А с этих запретит: http://www.mot.com/spin/getuid.cgi

http://www.motorola.com/internal/spin/getuid.cgi

Элемент

Card

События:

onenterbackward

Сработает при выборе элемента "prev"

onenterforward

Сработает при вызове карты

ontimer

Сработает по истечении времени у элемента "timer".

Атрибуты:

id - атрибут, позволяющий сослаться на эту карточку из других элементов. Ссылка на карточку состоит из символа "#" и значения ее атрибута id (#nextcard).

title - значение этого атрибута может быть использовано для озаглавливания экрана, в котором отображается карточка, а также может появится в списке ранее посещенных страниц, а также в любом другом месте по усмотрению микроброузера.

newcontext - может быть использован для того, чтобы сбросить состояние деки. Этот атрибут может иметь значение "true" или "false".

ordered - сообщает микроброузеру принадлежит ли эта карта к упорядоченному списку карт или нет. Разработчики могут использовать этот атрибут по своему усмотрению и разрабатывать либо деку с последовательным просмотром карточек, либо состоящую из одной большой карточки.




Немного более сложная дека в качестве примера:

<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN""http://www.wapforum.org/DTD/wml_1.1.xml"> <wml> <head> <access domain="motorola.com" path="/spin"/> </head> <template> <do type="accept" name="accept1" label="OK"> <go href="#accept"/> </do> </template> <card id="start" title="Start Here"> <p> Start Here. </p> </card> <card id="accept" title="Okay Card"> <do type="accept" name="accept1" label="Okay"> <go href="#accept2"/> </do> <p> Card Accept </p> </card> <card id="accept2" title="OK Card" > <do type="accept" > <go href="#start" /> </do> <p> Card Accept2 </p> </card> </wml>


Структура запроса


В XQuery запрос состоит из двух частей, называемых прологом запроса (query prolog) и телом запроса (query body). Пролог состоит из серии объявлений, которые определяют среду для обработки тела. Тело запроса - просто выражение, чье значение определяет результат запроса.

Пролог нужен только в том случае, если тело зависит от одного или нескольких пространств имен, схем или функций. Если такая зависимость существует, объекты, от которых зависит тело запроса должны быть объявлены в прологе запроса. Мы обсудим по отдельности объявления для пространства имен, схем и функций.

В объявлении пространства имен определяется префикс пространства имен и указывается его привязка к URI пространства имен. Префикс может быть любым идентификатором. В следующем объявлении пространства имен определяется префикс xyz и указывается его привязка. namespace xyz = "http://www.xyz.com/example/names"

Это объявление позволяет использовать префикс xyz в именах QName в теле запроса. Префикс связывается с URI некоторого пространства имен и служит в качестве уникального квалификатора для имен элементов, атрибутов и типов. Например, xyz:billing-address может уникально идентифицировать элемент billing-address, определенный в пространстве имен http://www.xyz.com/example/names. С одним пространством имен можно связать несколько префиксов.

В прологе запроса можно объявить пространство имен по умолчанию, применяемое ко всем неквалифицированным именам элементов и топов, и еще одно пространство имен по умолчанию, применяемое ко всем неквалифицированным именам функций. Ниже иллюстрируется синтаксис объявления пространств имен по умолчанию. default element namespace = "http://www.xyz.com/example/names" default function namespace = "http://www.xyz.com/example/functions"

Если пространства имен по умолчанию не введены, то неквалифицированные имена элементов, типов или функций считаются не относящимися к какому-либо пространству имен. Неквалифицированные имена атрибутов всегда считаются не относящимися к какому-либо пространству имен.




Помимо объявлений пространств имен пролог запроса может содержать одно или несколько объявлений импорта схемы. При объявлении импорта схемы указывается URI схемы, а также может быть указан второй URI, определяющий место, где может быть найден файл схемы. Цель импорта заключается в том, чтобы предоставить процессору запросов определения элементов, атрибутов и типов, которые объявлены в указанной схеме. Процессор запросов может использовать эти определения для проверки вновь сконструированных элементов, для оптимизации и для проведения статического анализа типов в запросе.

В схеме набор элементов, атрибутов и типов обычно определяется в некотором пространстве имен, называемом целевым пространством имен (target namespace) схемы, но префикс пространства имен не определяется. Поэтому при импорте схемы можно указать префикс пространства имен, привязанный к целевому пространству имен этой схемы. В следующем объявлении импорта схемы префикс пространства имен xhtml связывается с целевым пространством имен некоторой схемы, а также системе предоставляется отдельная , позволяющая найти эту схему. schema namespace xhtml = "http://www.w3.org/1999/xhtml" at "http://www.w3.org/1999/xhtml/xhtml.xsd"

Помимо объявлений пространства имен и импорта схем пролог запроса может содержать одно или несколько определений функции. Функции, определенные в прологе запроса, могут использоваться в теле запроса или в телах других функций.


ТАБЛИЦЫ СТИЛЕЙ


До сих пор при обсуждении XML я обходил стороной два важных вопроса. Первый из них касается того, как именно должны форматироваться элементы XML. (Вы наверняка пытались, но тщетно, найти инструкции по форматированию в приводимых фрагментах кода.) Второй же связан с тем, как браузеры смогут понимать нестандартные теги типа <publication>.

Ответ лежит в использовании таблиц стилей. Пользующиеся умеренной популярностью в Web каскадируемые таблицы стилей (Cascading Style Sheet, CSS) позволяют изменять форматирование известных тегов HTML и определять новые теги. В частности, на Web-сервере Network Magazine таблицы стилей CSS используются для стандартизации представления типичных элементов, таких, как <H1>, и для введения новых, таких, как врезки.

CSS могут служить и для форматирования документов XML, но это не очень удачный выбор. Главное достоинство XML в том, что он представляет формат документа, для возможных манипуляций, в виде древовидной структуры. К сожалению, CSS не способны взаимодействовать с деревом и могут только форматировать документы XML «как они есть». Вы можете вывести документ на экран в любом приглянувшемся формате, но не можете осуществить какое-либо избирательное представление его данных без применения языка сценариев. Более того, для использования CSS вам придется изучить еще один синтаксис.

Данные ограничения привели к созданию XSL. Это приложение XML со своей собственной семантикой (фиксированным набором элементов), следовательно, оно может быть использовано для создания таблиц стилей (шаблонов документов), понятных любой программе разбора XML.

Таблицы стилей XSL описывают, как документы XML должны преобразовываться в другие форматы, такие, как HTML или RTF. Но таблицы стилей XML — это нечто большее, чем просто преобразователи форматов; они также предоставляют механизм для манипулирования данными. Например, данные можно сортировать, производить по ним поиск, удалять или добавлять прямо из браузера.

Давайте рассмотрим какую-либо простую таблицу стилей, которой мы могли бы воспользоваться для представленного ранее приложения Editor Contacts.


<?xml version = “1.0” ?> <xsl:stylesheet xmlns:xsl=“http://www.w3.org/TR/WD-xsl”> <!–декларация, что документ является таблицей стилей и что он связан с xsl: namespace –> <xsl:template match=”/”> <!–Применить шаблон ко всему в исходном документе XML –> <HTML> <BODY> <H1>Editor Contacts</H1> <xsl:for-each select=”editor_contacts/editor”> <H2>Name: <xsl:value-of select=”first_name”> <xsl:value-of select=”last_name”/></H2> <P>Title: <xsl:value-of select=“title”/></P> <P>Publication: <xsl:value-of select=”publication”/></P> <P>Street Address: <xsl:value-of select=”address/street”/></P> <P>City: <xsl:value-of select=”address/city”/></P> <P>State: <xsl:value-of select=”address/state”/></P> <P>Zip: <xsl:value-of select=”address/zip”/></P> <P>E-Mail: <xsl:value-of select=”e_mail”/></P> </xsl:for-each> </BODY> </HTML> </xsl:template> </xsl:stylesheet>
При сохранении на диск под именем EDITORS.XSL (или любым другим) этот шаблон будет применен к EDITORS.XML при добавлении в него следующей строки после первой: <?xml-stylesheet type=”text/xsl” href= “editors.xsl” ?>
В конечном итоге текст на экране браузера будет выглядеть точно так же, как представленный ранее фрагмент HTML. Однако XSL может действовать как функция текстового процессора merge-print. Определенный как неотъемлемая часть пространства имен XSL, элемент xsl:for-each сообщает процессору о том, что он должен циклически обрабатывать все узлы в исходном файле XML. Атрибут xsl:value-of вставляет значение узла XML в элемент HTML. Таким образом, если вам придется вернуться к EDITORS.XML и вставить десятки или сотни контактных адресов, то они без каких-либо изменений будут отображаться в таблице стилей. Благодаря тому, что информацию о форматировании требуется передать только один раз, XML и XSL экономят пропускную способность. Таблицы стилей XSL имитируют функцию merge-print еще и в том, что они позволяют избирательно опускать поля данных при отображении.


Кроме того, вывод может быть отсортирован по любому конкретному полю данных. Для сортировки базы данных контактных адресов по фамилии редактора в прямом алфавитном порядке элемент xsl:for-each следует изменить следующим образом: <xsl:for-each select= “editor_contacts/editor” order-by=”+last_name”>
XSL способен также осуществлять условную трансформацию вывода в зависимости от значений различных элементов или атрибутов. Более того, он позволяет запрашивать данные с использованием множества разнообразных операторов шаблонов, символов подстановки, фильтров, булевых операторов и выражений множества. XML и XSL никоим образом не предназначены для замены SQL, к тому же вряд ли найдется много желающих хранить свои базы данных непосредственно в формате XML. Однако XSL открывает возможность разнообразного поиска по данным после их загрузки в браузер. Вам никогда уже не понадобится использовать для поиска информации примитивную встроенную команду браузера Find.
Значительный потенциал XML в качестве промежуточного программного обеспечения подкрепляется объектной моделью документа (Document Object Model, DOM), версия 1.0 которого была принята в качестве рекомендации W3C в октябре 1998 года. DOM возникла как спецификация для обеспечения переносимости сценариев JavaScript и программ на Java между браузерами Web и позднее эволюционировала в API для документов HTML и XML. Она определяет логическую структуру документов, способы доступа и манипулирования ими. Программисты могут создавать документы, управлять их структурой и добавлять, модифицировать или удалять элементы и содержимое.
DOM не оказывает никакого влияния на то, как следует писать документы XML и HTML. Вместо определения набора структур данных она представляет документы в соответствии с объектной моделью, такой, как древовидная структура, состоящая из узлов. Нет никакой необходимости использовать DOM просто для просмотра документов XML из браузера. Она применяется, когда по сценарию требуется изменить документ XML или обратиться к его данным.На сервере DOM может применяться для анализа поступивших от клиента файлов XML и соответствующей реакции на них. Кроме того, программистами DOM может использоваться в качестве промежуточного уровня для преобразования из формата базы данных в XML. При правильной реализации интерфейсов DOM пользователям никогда не потребуется знать, что данные хранятся в каком-либо ином формате, а не в XML.

Таймер


Элемент:

timer

Атрибуты:

value - промежуток времени в десятых долях секунды.

<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> <wml> <card id="first" ontimer="#next"> <timer value="100"/> <p>Wait ten seconds</p> </card> <card id="next"> <timer value="10"/> <onevent type="timer"> <go href="#first"/> </onevent> <p>Подождите минутку</p> </card> </wml>



Tamino - информационный сервер для электронного бизнеса


Деловой мир развивается все стремительнее, и, в свою очередь требует пересмотра и создания новых бизнес-процессов, которые должны быть реализованы за короткое время для того, чтобы сохранить конкурентноспособность предприятия. Электронный бизнес и работа в Интернет, находящиеся сегодня на периферии корпоративных ИТ, должны будут объединиться с последними.

Это обстоятельство приводит к необходимости создания такой инфраструктуры ИТ, в которой новые приложения смогут работать совместно с существующими компонентами, прикладными системами и людскими ресурсами. В то время как быстрое развитие электронного бизнеса и развитие будущих рынков предполагает состояние "перманентной революции", сохранение инвестиций, сделанных в оборудование, обслуживающий персонал клиента, требует принятия более эволюционных мер. ИТ должна быть способна реализовать радикальные изменения и быстро, и по возможности - плавно.

Вместе с тем электронный бизнес ставит новые проблемы:

Необходимость быстрой адаптации технологии в соответствие с быстро изменяющимися требованиями рынка Обеспечение соответствия скоростям передачи данных, иногда изменяющимся на порядки величин Необходимость соединения существующих островов ИТ без дублирования существующих промышленных решений Требование сокращения расходов на программирование в среде Интернет и администрирование серверов.

Tamino был создан для решения именно этих проблем.



ТЕГ — ЭТО СООБЩЕНИЕ


ICE является далеко не единственным предложенным стандартом, где XML применяется для определения коммуникационного протокола. К слову сказать, уже один тег , как он определен в BizTalk, помещает отраслевые множества данных на конвейер сообщений. Так, еще несколько протоколов Internet аналогично описываются с помощью XML. Это, например, Platform for Privacy Preferences (P3P) и Synchronyzed Multimedia Integration Language (SMIL, произносится как «смайл»). И не приходится сомневаться, что вскоре появятся еще.

Эти детища двух инициатив — одной, стремящейся более строго и полно регламентировать, что должен собой представлять правильно составленный документ XML, и второй, решившей применить XML к «диалоговым» приложениям, — показывают, что XML не удастся подвести под одну мерку.

В своей основе XML очень прост, но в реальном мире разные задачи, такие, как преобразование стилей, спецификации печатных данных и иерархические схемы, смешиваются настолько энергично, что в результате мы рискуем получить барочный букет угловых скобок. Однако с учетом того, что инструменты для упорядочения хаоса XML становятся все лучше, вполне вероятно, что его усложнение будет иметь положительный эффект, так как оно позволит решить с помощью XML и другие задачи вычислительного мира. Но мы должны считаться с фактом, что, как и HTML до него, XML имеет самостоятельную ценность и круг задач.

Роберт Ричардсон — внештатный редактор Network Magazine. Он организовал бесплатный электронный журнал Small Office TECH по адресу: .



Технологии баз данных для World-Wide Web: обзор


Даниэла Флореску, Алон Леви, Альберто Мендельсон

Журнал , #04-05/98



Технология Tamino


С выпуском Tamino компания Software AG представляет новое поколение СУБД, первый в мире информационный XML-сервер, являющийся быстродействующим, надежным, высоко масштабируемым продуктом, основанным на открытых стандартах. Компоненты Tamino обеспечивают решение поставленной задачи - обеспечивать быстрый, но плавный процесс изменения ИТ - поскольку Tamino объединяет технологии Интернет с современными достижениями в области разработки баз данных и средств доступа к существующим базам данных. Информационный сервер Tamino представляет собой совершенно новую разработку интегрированного решения, включающего в себя:

Технология X-Machine

Высокопроизводительный инструмент для хранения XML-данных в их оригинальном виде, включая возможность подключения функциональных расширений сервера, написанных пользователем, для выполнения различных операций преобразования документов.

Технология X-Machine позволяет хранить и искать объекты данных, относящихся к бизнес-процессам, в их оригинальном виде. X-Machine представляет собой первую в мире реализацию истинной базы данных XML.

Tamino поддерживает XML V.1.0, язык ссылок XLL, таблицы стилей XSL и подмножество XQL, а также концепцию пространства имен XML.

X-Machine включает в себя:

XML-процессор

Объекты XML, запоминаемые в XML-хранилище, описываются соответствующей схемой данных, выраженной в правилах отображения. Данная информация хранится в базе данных Tamino. Внутренний XML-процессор выполняет проверку правильности синтаксиса описателей объекта и отвечает за синтаксическую корректность (well-formed) структуры объектов XML. Процессор объектов

Процессор объектов используется при запоминании объектов XML в XML-хранилище. При этом структурированные данные (данные РСУБД) запоминаются в таблицах и колонках, соответствующих Описанию схемы. Обмен с внешними источниками данных выполняется с помощью компонента X-Node. Интерпретатор запросов XML

В качестве языка запросов используется XQL. Интерпретатор запросов обрабатывает полученный запрос совместно с Генератором объектов в целях поиска и формирования результата в виде XML-документа. Генератор объектов (Object Composer)



Данный компонент используется при поиске и чтении объектов. Используя уникальные идентификаторы объектов, сформированные X-Machine при их запоминании, Генератор объектов конструирует информационные объекты и возвращает их как результат выполнения запроса в виде XML-документов. В простейшем случае информационные объекты будут объектами XML. В сложных запросах для конструирования XML-объекта из традиционных источников данных Генератор объектов будет обращаться к Tamino X-Node или Tamino SQL Engine. Программы обслуживания

Tamino предоставляет ряд программ обслуживания информационного сервера. В качестве главного примера может служить программа загрузки XML-объектов (аналог утилиты массовой загрузки данных в традиционных СУБД).

Tamino SQL Engine



С помощью SQL-процессора реализованные в Tamino средства отображения данных в XML позволяют автоматически решать задачу их представления в виде объектов Интернет, и наоборот, информационные объекты Интернет могут стать доступными в виде реляционных данных для стандартных приложений, ориентированных на SQL.

Для поддержки работоспособности SQL приложений, в состав Tamino входит SQL-процессор, обеспечивающий также и среду хранения реляционных данных. SQL-процессор поддерживает выполнение операторов SQL версии 2 в части манипулирования определения и управления данными (DML, DDL, DCL), а также выполнение ACID-транзакций.

SQL-процессор получает SQL-запросы от Tamino несколькими способами:

Внутренние обращения Tamino X-Machine SQL-приложения либо с помощью встроенного SQL, либо с помощью стандартных интерфейсов ODBC, JDBC, OLE DB. Диспетчер Tamino

Кроме того, SQL-процессор предоставляет препроцессоры для компиляторов со стандартных языков программирования.

Диспетчер Tamino



Инструментарий для администрирования объектов Tamino в Интернет. Для выполнения функций администрирования (создание базы данных, запуск/остановка сервера, сохранение/восстановление, загрузка данных, и т.д.) в состав диспетчера Tamino входит агент, устанавливаемый на каждом узле, где развернут сервер Tamino.


Кроме того, Диспетчер Tamino взаимодействует с Генератором схемы Tamino для настройки параметров XML-процессора (Parser), задания правил отображения данных и установки программ-расширений сервера Tamino.

Расширения сервера



Архитектура Tamino позволяет пользователям встраивать специализированные функции для дополнительной обработки информации, обеспечивающие возможности работы с данными, хранящимися в Tamino, которые, в свою очередь, могут быть представлены как XML, так и не-XML структуры. Программы-расширения сервера устанавливаются на узле сервера с помощью Диспетчера Tamino, и, будучи установленными, доступны пользователям как стандартные встроенные функции сервера.

Кроме того, расширения сервера могут использоваться для реализации динамического отображения данных, т.е. преобразования структуры XML в структуру РУСБД на основании значения элемента документа.

Расширения сервера являются составной частью Tamino, и могут быть написаны на C, C++ или на других языках, поддерживающих COM/DCOM. Предлагаемый инструментарий среды разработки оснащен помощниками (Wizards), упрощающих процесс написания программ. Применение расширений сервера позволит уменьшить нагрузку на сеть за счет перевода обработки данных с клиента на сервер.

Описание схемы



Компонент Описание схемы (Schema Description) Tamino составляет его базу знаний, содержащую правила отображения, хранения и конструирования объектов XML. Правила построения объектов основаны на информации о схеме данных, поддерживаемой администратором сервера. Правила используются для:

Отображения структур XML во внутреннюю структуру XML-хранилища, обеспечивая хранение XML-документов в их исходном виде Отображения структур XML в структуры существующих СУБД и наоборот, что делает возможным объединение данных из разнородных источников Отображения структур существующих файлов Adabas Отображения структур XML в структуру другого сервера Tamino

Правила построения и отображения структур данных поддержаны соотвествующим графическим инструментарием, входящим в состав Администратора Tamino.



X-Node



С помощью компонента Tamino X-Node пользователь получает доступ к разнородным и распределенным источникам данных. В качестве источников данных могут быть базы данных, файловые системы, или данные, полученные из систем передачи сообщений. Компонент X-Node позволяет представить прикладной программе все эти источники, как единый источник необходимых данных, независимо от их физического расположения. X-Node позволяет перегруппировывать данные, объединять существующие базы данных с новыми источниками данных, поскольку все обрабатываемые данные представляются в виде одного объекта XML.

С помощью X-Node предоставляется возможность использования существующих баз данных предприятия в их существующем виде и на существующих платформах, обеспечивая доступ к ним из Интернет.

Tamino SDK

Комплект инструментальных средств разработки приложений, обеспечивающий взаимодействие Tamino с XQL, SQL или объектно-ориентированными приложениями (DOM), и состоит из набора следующих интерфейсов:

Интерфейс прямого доступа к объектам XML с помощью традиционной их адресации по URL. Интерфейс языка запросов XQL, существующего в настоящее время в виде проекта стандарта. Интерфейсы OLE DB, ODBC, JDBC и DCOM для приложений, использующих SQL и объектно-ориентированные технологии.

Tamino поддерживает спецификации модели DOM на уровне W3C's Document Object Model Recommendation Level 1, что делает возможным предоставлять клиентам объекты XML как объекты DOM. Данная возможность позволяет приложению получить доступ к элементу документа, обработать его и изменять его значения. Модель DOM реализована на сервере в виде интерфейса с прикладной программой клиента, что поддерживает идеологию "тонкого" клиента.


Текст


У элемента p нет атрибутов

У элемента br нет атрибутов



Telnet


Команда telnet позволяет вам ``войти" в терминальный сеанс работы с удаленным компьютером. Формат команды:

telnet [ remote_host ]

где remote_host представляет собой адрес удаленной машины. Пример:

telnet aries

В ответ вы получите обычное приглашение с удаленной машины. Вы вводите свое имя и пароль и оказываетесь в режиме терминальной работы с машиной aries. Для разрыва связи и возвращения на локальную машину используйте команду exit.

Имя удаленной машины в командной строке telnet'а является необязательным параметром. Введя команду telnet без параметров вы немедленно получите приглашение telnet&gt и теперь, пользуясь командами самого telnet'а вы можете установить соединение с удаленной машиной или настроить параметры telnet'а. Наиболее полезной командой telnet'а для начинающих пользователей является команда ``?", выдающая краткую справку по командам telnet'а. Пример работы с командами telnet'а:

% telnet

telnet&gt ?

Commands may be abbreviated. Commands are:

close close current connection

display display operating parameters

mode try to enter line-by-line or character-at-a-time mode

open connect to a site

quit exit telnet

send transmit special characters ('send ?' for more)

set set operating parameters ('set ?' for more)

unset unset operating parameters ('unset ?' for more)

status print status information

toggle toggle operating parameters ('toggle ?' for more)

slc change state of special charaters ('slc ?' for more)

z suspend telnet

! invoke a subshell

? print help information

telnet&gt quit

%

Если вы уже установили терминальную связь с удаленным компьютером вы можете вернуться в командный режим telnet'а с помощью ввода управляющей последовательности &lt Esc&gt (если на клавиатуре вы не нашли такой клавиши, вы вводите &lt Esc&gt с помощью одновременного нажатия двух клавиш Ctrl-[). Это обычно используется для изменения коммуникационных параметров.

Более подробную информацию о формате и назначении команд telnet'а вы можете получить дав следующую команду на приглашение telnet'а:

telnet&gt ? command

где command - имя команды по которой вы хотите получить подробную справку.



Тип 'Application'


Этот тип используется для данных, неподпадающих под остальные категории, в частности, для данных, обрабатываемых прикладными почтовыми программами. Это информация, которая должна быть обработана соответствующим приложением для того, чтобы принять наглядную либо исполняемую для получателя форму. Предполагаемое использование для этого типа включает в себя пересылку файлов по почте, таблицы, данные для почтовых систем расписания, языки лдя "активной" (вычислительной) почты. (Последняя, в частности, может поднять проблемы безопасности, которые должны быть поняты разработчиками ПО и рассмотрены ниже в параграфе "Application/PostScript").

Например, тот, кто занимается расписанием встреч, может определить стандартное представление информации о датах запланированных встреч. "Умный" пользовательский почтовый агент может использовать эту информацию для проведения диалога с пользователем, и может затем посылать в дальнейшем почту, основанную на том диалоге. Вообще, существует несколько "активных" почтовых языков, разработанных для специализированных программ, которые посылаются по почте и автоматчески запускаются в системе получателя.

Подобные приложения могут быть определены как подтипы для типа "application". Изначально предопределено два подтипа: "octet-stream" и "PostScript".

В общем, подтип для 'application' зачастую может быть именем приложения, для которого предназначены пересылаемые данные. Однако, это не означает, что любое имя прикладной программы может свободно использоваться как подтип для 'application'. Такие употребления (кроме подтипов, начинающихся с "x-") должны быть зарегестрированы в IANA.



Тип 'Audio'


Этот подтип означает, что тело содержит аудио-данные. Хотя пока еще нет консенсуса по "идеальному" аудио-формату для компьютеров, сейчас имеется сильная потребность в универсальном формате.

Предопределенный подтип - "basic" введен в ответ на это требование, обеспечивая минимальный примитивный аудио-формат. Ожидается определение в дальнейшем более "богатых" форматов, обеспечивающих более высокое качество воспроизведения.

Содержимое тела, имеющего подтип "audio/basic", - аудио-данные в 8-битной форме, кодированные с использованием ISDN mu-law. Формат, соответствующий этому подтипу, предполагает максимальную частоту звучания 8000 Hz и единственный канал.

Формальный синтаксис лдя поля 'Content-Type': audio_тип := "audio" "/" ("basic" / подтип-расширение)



Тип 'Image'


Этот тип означает, что тело письма содержит графический объект. Его подтипы соответствуют конкретным графическим форматам. Их значения нечувствительны к регистру букв. Два предопределенных подтипа - "jpeg" для формата JPEG с кодированием JFIF, и "gif" - для формата GIF.

Формальный синтаксис поля 'Content-Type': image_тип := "image" "/" ("gif" / "jpeg" / подтип-расширение)



Тип экрана (BIOS совместимость)


Этот параметр обычно устанавливается в файле конфигурации. Установка Direct to screen означает быструю запись информации непосредственно на экран. Но при этом могут возникнуть проблемы если на локальной машине используется Windows, который пишет на экран через BIOS. Для обеспечения Windows совместимости можно установить соответствующий параметр.



Тип 'message'


При пересылке почты часто возникает необходимость включить внутрь письма другое письмо. Для этого и используется тип 'message'.

Основной подтип - "rfc822" - не требует параметров в поле Content-Type. Дополнительные подтипы - "partial" и "External-body" - предполагают наличие параметров.

ЗАМЕЧАНИЕ: Для перенаправляемой и возвращаемой почты можно было бы определить отдельные подтипы, однако, такая почта может пересылаться как multipart-письмо, в котором первая часть содержит некоторую пояснительную текстовую информацию, а другая, имеющая тип 'message/rfc822', содержит перенаправляемое/возвращаемое письмо. Подобный способ перенаправления/возвращения почты сохраняет информацию о типе оригинального письма и позволяет ему быть корректно представленным получателю, и поэтому настоятельно рекомендуется.



Тип 'multipart'


Этот тип используется, если один или более различных наборов данных заключены в одном письме. Каждая часть тела должна иметь синтакс письма RFC 822 (то есть, иметь заголовок,ь пустую строку и тело), но должна иметь открывающую и закрывающую границы.

Часть письма не должна интерпретироваться как настоящее письмо RFC 822. Вообще, для части письма наличие заголовка не обязательно, так что она может начинаться и с пустой строки, но при этом, все признаки, описываемые в заголовке, имеют значение по умолчанию. Для частей письма имеют смысл только поля, описывающие содержимое, то есть. начтинающиеся с "Content-". Все остальные поля, необходимые в заголовке верхнего уровня, обычно игнорируются в частях письма при обработке почты, более того, в некоторых почтовых шлюзах они могут быть просто удалены. Для экспериментальных и частных целей могут использоваться "X-" поля, но информация, в них заложенная, может быть потеряна при прохождении некоторых почтовых шлюзов.

ЗАМЕЧАНИЕ: Различие между письмом RFC 822 и частью письма MIME является маленькой, но важной. Шлюз между почтой Internet и X.400, например, должен иметь возможность отличить часть письма, содержащую графическое изображение, от части письма, содежащей вложенное письмо, телом которого является графическое изображение. Для представления последнего соответствующая часть письма должна иметь "Content-Type: message" и ее тело после пустой строки должно являться вложенным письмом со своим собственным полем заголовка "Content-Type: image". Схожесть синтаксиса обеспечивает легкость конверсии от письма к части письма, но различие между ними должно быть усвоено производителями ПО.

Граница части письма не должна появляться внутри самой части письма.

Все существующие и будущие подтипы типа "multipart" должны иметь идентичный синтаксис. Они могут различаться своей семантикой. Это требование гарантирует, что совместимые пользовательские агенты смогут по крайней мере распознать и разделить части многочастного письма, даже имеющего неизвестный им подтип.

Как упомянуто в определении поля Content-Transfer-Encoding, использование других значений кроме "7bit", "8bit" или "binary" запрещено для типа "multipart". Почтовые шлюзы и другие почтовые агенты часто вносят изменения в заголовки верхнего уровня. В частности, они могут добавлять, убирать, переупорядочивать определенные поля. Такие изменения запрещены для заголовков частей письма, находяшихся внутри тела типа "multipart".



Тип терминала


По умолчанию устанавливается эмуляция терминалов VT102 и Textronix. При необходимости можно сузить эту интерпретацию команд установив а) Только VT102 и графические команды Textronix игнорируются или б) Простой терминал без какой бы то ни было эмуляции.



Тип 'Text'


Тип 'text' предназначен для пересылки текстовых материалов. Это значение поля - по умолчанию. Для обозначения языковой кодировки текста используется параметр "charset" для некоторых подтипов, включая основной подтип, "text/plain", соответствующий простому (неформатированному) тексту. В Internet'овской почте значением Content-Type по умолчанию является следующее: "text/plain; charset=us-ascii". Если текст является размеченным и нет соответствующего ПО для корректного визуального представления этого текста пользователю, имеет смысл сообщить ему подтип этих текстовых данных.



Тип 'Video'


Этот тип означает, что в теле письма содержится анимационное изображение, возможно, со звуком и цветом. Термин "video" используется безотносительно к технологии получения подвижного во времени изображения. Подтип "mpeg" указывает на видео, кодированное в соответствии со стандартом MPEG.

Хотя MIME-стандарт запрещает смешение разнородных мультимедийных данных в одном теле (письма или части письма), многие так называемые "video"-форматы включают синхронизированный звук, что допускается для подтипов типа "video".

Формальный синтаксис лдя поля 'Content-Type': video-type := "video" "/" ("mpeg" / подтип-расширение)



Типы


При создании запроса иногда необходимо сослаться на некоторый тип. Например, как уже было отмечено, при определении функции требуется описать типы параметров функции и ее результата. В других видах выражений XQuery также требуется возможность ссылаться на некоторые типы.

Один из способов сослаться на тип - это указать его квалифицированное имя, или QName. QName может указывать на встроенный тип, такой как xs:integer, или на тип, который определен в некоторой схеме, такой как abc:address. Если в QName имеется префикс пространства имен (часть, расположенная слева от двоеточия), этот префикс должен быть привязан к некоторому идентификатору пространства имен. Это связывание достигается путем описываемого в следующем разделе объявления пространства имен в прологе запроса.

Еще один способ сослаться на тип - сделать это с помощью родового ключевого слова, такого как element или attribute. За этим ключевым словом может следовать QName, которое в большей степени ограничивает имя или тип узла. Например, element обозначает любой элемент, element shipto - любой элемент с именем shipto; и element of type abc:address означает элемент, тип которого - address, объявленный в пространстве имен abc. Ключевое слово attribute обозначает любой атрибут, node - любой узел, а item - любой объект (узел или атомарное значение).

В XQuery также предусмотрен дополнительный синтаксис, который позволяет ссылаться на другие виды узлов и на типы элементов, которые определены в локальной части схемы. Например, element city in customer/address указывает на элемент с именем city, как это определено в контексте схемы customer/address.

За ссылкой на тип может следовать один из трех индикаторов присутствия: означает , означает , а означает . Отсутствие индикатора присутствия означает присутствие ровно одного экземпляра указанного типа. Проиллюстрируем использование индикаторов присутствия.

element memo?означает возможное появление элемента с именем memo
element of type order+означает один или несколько элементов с типом order
element*означает любое число любых элементов
attribute?означает необязательный атрибут с любым именем и типом
<


Ссылки на тип появляются не только в определениях функции, но и других местах. Одно из таких мест - второй операнд операции instance of, которая возвращает true, если ее первый операнд является экземпляром типа, указанного во втором операнде. Следующие примеры иллюстрируют использование операции instance of (предполагается, что префикс xs привязан к пространству имен схемы ).
49 instance of xs:integerвозвращает true
"Hello" instance of xs:integerвозвращает false
<partno>369</partno> instance of element*возвращает true
$a instance of element shiptoвозвращает true, если $a привязана к элементу с именем shipto
Первая часть typeswitch состоит из выражения, тип которого проверяется (выражение операнда, operand expression), и необязательной переменной, связываемой со значением выражения операнда. Далее следуют одно или несколько операторов case, каждый из которых содержит тип и выражение. Операнд выражения по очереди проверяется на соответствие типу, указанному в каждом из условий case. Первый оператор case, для которого операнд выражения является экземпляром заданного типа, называется действующим случаем (effective case); выражение в этом операторе case вычисляется и служит результатом typeswitch. Если выражение операнда не соответствует ни одному из типов, указанных в условиях case, результат typeswitch берется из последнего оператора, действующего по умолчанию.

Проиллюстрируем использование typeswitch. Это выражение может появиться в цикле, где переменная $customer итерируется над множеством элементов customer, каждый из которых имеет подэлемент с именем billing-address. Подэлементы billing-address могут относиться к нескольким различным типам, каждый из которых требуется обрабатывать особым образом. Переменная $a связывается с billing-address, а затем вычисляется одно из нескольких выражений, в зависимости от динамического типа $a. В каждом операторе case $a имеет особый тип, например, в первом условии case типом $a должен быть element of type USAddress.


Если выясняется, что элемент billing-address не соответствует ни одному из ожидаемых типов, результатом выражения является . typeswitch ($customer/billing-address) as $a case element of type USAddress return $a/state case element of type CanadaAddress return $a/province case element of type JapanAddress return $a/prefecture default return "unknown"

Имена типов также используются в трех внешне похожих выражениях XQuery, называемых cast, treat и assert. Каждое из этих выражений содержит ключевое слово, ссылку на тип и выражение, заключенное в скобки.

Выражение cast служит для преобразования результата выражения к одному из встроенных типов XML Schema. Поддерживается предопределенный набор преобразований. Например, результат выражения $x div 5 может быть приведен к типу xs:double с помощью выражения cast as xs:double($x div 5). В случае неудачного выполнения операция приведения типа может вернуть значение ошибки. Например, выполнение cast as xs:integer($mystring) будет успешным, если $mystring - строковое представление integer, но вернет ошибку, если $mystring имеет значение . Выражение cast не может использоваться для приведения значения к типу, определенному пользователем; для этого ему следует написать специальную функцию.

Выражение treat позволяет гарантировать, что динамический (времени исполнения) тип выражения соответствует предполагаемому типу. Например, предположим, что статическим(времени компиляции) типом выражения $customer/shipping-address является Address. Некоторое подвыражение может иметь смысл только для значений, соответствующих подтипу Address, такому как USAddress. Создатель подвыражения может использовать выражение treat для объявления ожидаемого типа подвыражения. treat as USAddress($customer/billing-address)

В отличие от cast, выражение treat на самом деле не меняет тип операнда. Выполнение происходит в два этапа: (1) операнду присваивается некоторый статический тип, который может использоваться для проверки типа при компиляции запроса; (2) во время выполнения, если реальное значение выражения не соответствует указанному типу, возвращается значение ошибки.



Чтобы понять, как процессор запросов мог бы использовать информацию, предоставляемую выражением treat, рассмотрим следующий пример. $customer/billing-address/zipcode

Компилятор XQuery, проверяющий типы, мог бы решить, что в этом примере имеется ошибка типа, поскольку статическим типом $customer/billing-address является Address, а тип Address, в общем случае, не имеет подэлемента zipcode. Однако в следующей формулировке статический тип выражения меняется на USAddress, у которого есть подэлемент zipcode, и ошибка типа исчезает. (treat as USAddress ($customer/billing-address))/zipcode

Как и treat, выражение assert используется для предоставления процессору запросов информации, которая может оказаться полезной для проверки типов. Выражение assert сообщает процессору запросов, что его выражение операнда имеет некоторый статический тип. Если процессор производит статическую проверку типов, он может породить ошибку, если окажется не в состоянии проверить, что данное выражение соответствует заявленному типу. Выражение assert является более строгим, чем выражение treat, поскольку оно относится к статическому типу выражения и, следовательно, не зависит от входных данных и может быть проверено перед выполнением запроса. С другой стороны, выражение treat относится к динамическому типу выражения и, как следствие, зависит от входных данных и может быть проверено только при выполнении запроса.

В следующем примере будет генерироваться ошибка типа времени компиляции, если статическим типом $customer/billing-address является Address. (assert as USAddress ($customer/billing-address))/zipcode

В XQuery не требуется, чтобы в реализации поддерживалась статическая проверка типов. Для процессора запросов, который не обеспечивает статическую проверку, assert эквивалентно treat.


ТО, ЧТО ВЫ ВИДИТЕ, — ЭТО ВСЕ, ЧТО ВЫ ПОЛУЧАЕТЕ


По сути, HTML — это технология представления информации, он описывает то, как браузер должен скомпоновать текст и график на странице. В результате «то, что вы видите, — это все, что вы получаете». Нет никакого способа описать данные независимо от отображения этих данных (за исключением чрезвычайно слабой системы ключевых слов в заголовке страницы Web). Это главная причина, почему так трудно найти нужную информацию с помощью механизма поиска.

Клиент не имеет никаких более-менее приемлемых средств извлечения данных со страницы Web для дальнейшей работы с ними. При наличии твердой руки вы можете вставить содержимое таблицы HTML в электронную таблицу, но это не решение! Далее, на любой конкретной странице Web клиент получает только одно представление конкретного множества данных.

Предположим, что вы просматриваете список аукционов eBay, упорядоченный по дате открытия торгов. Если вы захотите взглянуть на тот же список, но отсортированный по дате закрытия торгов, то вашему браузеру придется посылать новый запрос серверу. В свою очередь серверу придется заново отправлять полную страницу HTML со списком аукционов. Такого рода манипулирование данными ведет к значительному увеличению числа обращений к серверам Web и затрудняет, таким образом, их дальнейшее масштабирование.

Другая проблема с HTML в том, что это «плоский» язык, т. е. авторы не могут использовать его для предоставления информации об иерархии данных. Далее, он непоследователен и поэтому затрудняет разбор текста программным обеспечением. Например, хотя большинство открывающих тегов (такие, как <B> или <H1>) имеет соответствующие закрывающие теги, некоторые (например, <P>) их не имеют.

Простым решением для некоторых из перечисленных проблем было бы введение дополнительных тегов HTML, таких, как <NAME>, <DATE> или <PRICE>. С их помощью клиент мог бы определить, что собой представляют данные, и отображать их по-разному или экспортировать по запросу пользователя. История, однако, показывает, что введение дополнительных тегов для HTML может занять годы; консенсуса по поводу того, что они должны значить, редко когда удается достичь быстро, если он вообще возможен.


Если же вы решите не дожидаться изменения стандарта, то имейте в виду, что вы создаете нечто свое, нестандартное и тем самым отказываетесь от одного из главных преимуществ HTML.

Поэтому в 1996 году члены рабочей группы Консорциума World Wide Web (W3C, http://www.w3.org) вернулись к рассмотрению стандартного обобщенного языка разметки (Standard Generalized Markup Language, SGML), сильно упрощенным потомком которого является HTML. Предложенный в 1974 году Чарльзом Голдфарбом, SGML представляет собой метаязык — систему для описания других языков. При всех своих возможностях он слишком сложен для большинства браузеров Web: одна спецификация SGML занимает свыше 500 страниц.

Упростив SGML для использования с Web, группа предложила XML (рекомендация W3C по статусу на февраль 1998 года). XML представляет собой подмножество SGML, причем любой действительный документ XML является действительным документом SGML. И, как и SGML, XML — это метаязык, определяющий другие языки разметки для специфических целей. Например, язык синхронизированной интеграции мультимедиа (Synchronized Multimedia Integration Language, SMIL) базируется на XML.

XML используется для разметки стандартных документов во многом так же, как HTML. Однако XML превосходит его при работе со структурированными данными, такими, как результаты запроса, метаинформация об узле Web или элементы и типы схемы.

Документ XML выглядит во многом похожим на HTML. Он также состоит из текстовых фрагментов, аннотированных заключенными в угловые скобки тегами. Однако, в отличие от HTML, смысл тега зависит от регистра, а каждый открывающий тег должен во всех случаях иметь парный закрывающий тег.