diff options
Diffstat (limited to 'ru-ru')
| -rw-r--r-- | ru-ru/json-ru.html.markdown | 61 | ||||
| -rw-r--r-- | ru-ru/lua-ru.html.markdown | 2 | ||||
| -rw-r--r-- | ru-ru/paren-ru.html.markdown | 196 | ||||
| -rw-r--r-- | ru-ru/python-ru.html.markdown | 109 | ||||
| -rw-r--r-- | ru-ru/python3-ru.html.markdown | 54 | ||||
| -rw-r--r-- | ru-ru/swift-ru.html.markdown | 589 | ||||
| -rw-r--r-- | ru-ru/xml-ru.html.markdown | 130 | 
7 files changed, 1088 insertions, 53 deletions
diff --git a/ru-ru/json-ru.html.markdown b/ru-ru/json-ru.html.markdown new file mode 100644 index 00000000..52af3696 --- /dev/null +++ b/ru-ru/json-ru.html.markdown @@ -0,0 +1,61 @@ +--- +language: json +filename: learnjson-ru.json +contributors: +  - ["Anna Harren", "https://github.com/iirelu"] +  - ["Marco Scannadinari", "https://github.com/marcoms"] +translators: +  - ["Dmitry Bessonov", "https://github.com/TheDmitry"] +lang: ru-ru +--- + +JSON - это очень простой формат обмена данными, и это будет самый легкий +курс из когда-либо представленных "Learn X in Y Minutes". + +В чистом виде у JSON нет фактических комментариев, но большинство парсеров примут +комментарии в Си-стиле (//, /\* \*/). Для таких целей, конечно, все правильно +будет на 100% с точки зрения JSON. К счастью, в нашем случае данные скажут сами за себя. + +```json +{ +  "ключ": "значение", +   +  "ключи": "должны всегда заключаться в двойные кавычки", +  "числа": 0, +  "строки": "Пρивет, миρ. Допускаются все unicode-символы вместе с \"экранированием\".", +  "содержит логический тип?": true, +  "ничего": null, + +  "большое число": 1.2e+100, + +  "объекты": { +    "комментарий": "Большинство ваших структур будут представлять из себя объекты.", + +    "массив": [0, 1, 2, 3, "Массивы могут содержать в себе любой тип.", 5], + +    "другой объект": { +      "комментарий": "Они могут быть вложенными, и это очень полезно." +    } +  }, + +  "бессмыслие": [ +    { +      "источники калия": ["бананы"] +    }, +    [ +      [1, 0, 0, 0], +      [0, 1, 0, 0], +      [0, 0, 1, "нео"], +      [0, 0, 0, 1] +    ] +  ], +   +  "альтернативный стиль": { +    "комментарий": "проверьте это!" +  , "позиция запятой": "неважна, хоть и перед значением, все равно правильно" +  , "еще один комментарий": "как хорошо" +  }, + +  "это было недолго": "И вы справились. Теперь вы знаете все о JSON." +} +``` diff --git a/ru-ru/lua-ru.html.markdown b/ru-ru/lua-ru.html.markdown index 6f515975..da9ced6a 100644 --- a/ru-ru/lua-ru.html.markdown +++ b/ru-ru/lua-ru.html.markdown @@ -1,5 +1,5 @@  --- -language: lua +language: Lua  filename: learnlua-ru.lua  contributors:      - ["Tyler Neylon", "http://tylerneylon.com/"] diff --git a/ru-ru/paren-ru.html.markdown b/ru-ru/paren-ru.html.markdown new file mode 100644 index 00000000..9b801e46 --- /dev/null +++ b/ru-ru/paren-ru.html.markdown @@ -0,0 +1,196 @@ +--- +language: Paren +filename: learnparen-ru.paren +contributors: +  - ["KIM Taegyoon", "https://github.com/kimtg"] +translators: +  - ["Dmitry Bessonov", "https://github.com/TheDmitry"] +lang: ru-ru +--- + +[Paren](https://bitbucket.org/ktg/paren) - это диалект языка Лисп. Он спроектирован как встроенный язык. + +Примеры взяты <http://learnxinyminutes.com/docs/racket/>. + +```scheme +;;; Комментарии +# комментарии + +;; Однострочные комментарии начинаются с точки с запятой или символа решетки + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 1. Примитивные типы данных и операторы +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Числа +123 ; int +3.14 ; double +6.02e+23 ; double +(int 3.14) ; => 3 : int +(double 123) ; => 123 : double + +;; Обращение к функции записывается так: (f x y z ...), +;; где f - функция, а x, y, z, ... - операнды +;; Если вы хотите создать буквальный список данных, используйте (quote), чтобы +;; предотвратить ненужные вычисления +(quote (+ 1 2)) ; => (+ 1 2) +;; Итак, некоторые арифметические операции +(+ 1 1)  ; => 2 +(- 8 1)  ; => 7 +(* 10 2) ; => 20 +(^ 2 3) ; => 8 +(/ 5 2) ; => 2 +(% 5 2) ; => 1 +(/ 5.0 2) ; => 2.5 + +;;; Логический тип +true ; обозначает истину +false ; обозначает ложь +(! true) ; => false +(&& true false (prn "досюда не доходим")) ; => false +(|| false true (prn "досюда не доходим")) ; => true + +;;; Символы - это числа (int). +(char-at "A" 0) ; => 65 +(chr 65) ; => "A" + +;;; Строки - это массив символов с фиксированной длиной. +"Привет, мир!" +"Benjamin \"Bugsy\" Siegel"   ; обратная косая черта экранирует символ +"Foo\tbar\r\n" ; включает управляющие символы в стиле Cи: \t \r \n + +;; Строки тоже могут объединяться! +(strcat "Привет " "мир!") ; => "Привет мир!" + +;; Строка может трактоваться подобно списку символов +(char-at "Apple" 0) ; => 65 + +;; Выводить информацию достаточно легко +(pr "Я" "Paren. ") (prn "Приятно познакомиться!") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 2. Переменные +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Вы можете создать или инициализировать переменную, используя (set) +;; имя переменной может содержать любой символ, исключая: ();#" +(set some-var 5) ; => 5 +some-var ; => 5 + +;; Обращение к переменной, прежде не определенной, вызовет исключение +; x ; => Неизвестная переменная: x : nil + +;; Локальное связывание: Используйте лямбда-вычисление! `a' и `b' связывается +;; с `1' и `2' только в пределах (fn ...) +((fn (a b) (+ a b)) 1 2) ; => 3 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. Коллекции +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Списки + +;; Списки подобны динамическому массиву (vector). (произвольный доступ равен O(1).) +(cons 1 (cons 2 (cons 3 (list)))) ; => (1 2 3) +;; `list' - это удобный конструктор списков с переменным числом элементов +(list 1 2 3) ; => (1 2 3) +;; и quote может также использоваться для литеральных значений списка +(quote (+ 1 2)) ; => (+ 1 2) + +;; Можно еще использовать `cons', чтобы добавить элемент в начало списка +(cons 0 (list 1 2 3)) ; => (0 1 2 3) + +;; Списки являются основным типом, поэтому для них предусмотрено *много* функций +;; немного примеров из них: +(map inc (list 1 2 3))          ; => (2 3 4) +(filter (fn (x) (== 0 (% x 2))) (list 1 2 3 4))    ; => (2 4) +(length (list 1 2 3 4))     ; => 4 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. Функции +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Используйте `fn' для создания функций. +;; Функция всегда возвращает значение своего последнего выражения +(fn () "Привет Мир") ; => (fn () Привет Мир) : fn + +;; Используйте скобки, чтобы вызвать все функции, в том числе лямбда-выражение +((fn () "Привет Мир")) ; => "Привет Мир" + +;; Назначить функцию переменной +(set hello-world (fn () "Привет Мир")) +(hello-world) ; => "Привет Мир" + +;; Вы можете сократить это, используя синтаксический сахар определения функции: +(defn hello-world2 () "Привет Мир") + +;; Как и выше, () - это список аргументов для функции +(set hello +  (fn (name) +    (strcat "Привет " name))) +(hello "Стив") ; => "Привет Стив" + +;; ... или, что эквивалентно, используйте синтаксический сахар определения: +(defn hello2 (name) +  (strcat "Привет " name)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 4. Равенство +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; для чисел используйте `==' +(== 3 3.0) ; => true +(== 2 1) ; => false + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 5. Поток управления +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Условный оператор + +(if true               ; проверка выражения +    "это - истина"   ; тогда это выражение +    "это - ложь") ; иначе другое выражение +; => "это - истина" + +;;; Циклы + +;; Цикл for для чисел +;; (for ИДЕНТИФИКАТОР НАЧАЛО КОНЕЦ ШАГ ВЫРАЖЕНИЕ ..) +(for i 0 10 2 (pr i "")) ; => печатает 0 2 4 6 8 10 +(for i 0.0 10 2.5 (pr i "")) ; => печатает 0 2.5 5 7.5 10 + +;; Цикл while +((fn (i) +  (while (< i 10) +    (pr i) +    (++ i))) 0) ; => печатает 0123456789 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 6. Изменение +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Используйте `set', чтобы назначить новое значение переменной или памяти +(set n 5) ; => 5 +(set n (inc n)) ; => 6 +n ; => 6 +(set a (list 1 2)) ; => (1 2) +(set (nth 0 a) 3) ; => 3 +a ; => (3 2) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 7. Макросы +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Макросы позволяют вам расширять синтаксис языка. +;; Paren-макросы легкие. +;; Фактически, (defn) - это макрос. +(defmacro setfn (name ...) (set name (fn ...))) +(defmacro defn (name ...) (def name (fn ...))) + +;; Давайте добавим инфиксную нотацию +(defmacro infix (a op ...) (op a ...)) +(infix 1 + 2 (infix 3 * 4)) ; => 15 + +;; Макросы приводят к неясному коду, т.е. вы можете затереть существующие переменные! +;; Они являются кодопреобразующей конструкцией. +``` diff --git a/ru-ru/python-ru.html.markdown b/ru-ru/python-ru.html.markdown index d59d3e21..a0e2b474 100644 --- a/ru-ru/python-ru.html.markdown +++ b/ru-ru/python-ru.html.markdown @@ -10,20 +10,20 @@ filename: learnpython-ru.py  ---  Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из -самых популярных языков. Я люблю его за понятный и доходчивый синтаксис  — это -почти что исполняемый псевдокод. +самых популярных языков. Я влюбился в Python за понятный и доходчивый синтаксис  — это +почти исполняемый псевдокод.  С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh)  или louiedinh [at] [почтовый сервис Google] -Замечание: Эта статья относится к Python 2.7, но должно работать и в Python 2.x. -Скоро будет версия и для Python 3! +Замечание: Эта статья относится к Python 2.7, но должно работать и в других версиях Python 2.x. +Чтобы изучить Python 3.x, обратитесь к статье по Python 3.  ```python  # Однострочные комментарии начинаются с символа решётки.  """ Многострочный текст может быть       записан, используя 3 знака " и обычно используется -    в качестве комментария +    в качестве встроенной документации  """  #################################################### @@ -43,7 +43,7 @@ filename: learnpython-ru.py  # целых чисел, и результат автоматически округляется в меньшую сторону.  5 / 2 #=> 2 -# Чтобы научиться делить, сначала нужно немного узнать о числах +# Чтобы делить правильно, сначала нужно немного узнать о числах  # с плавающей запятой.  2.0     # Это число с плавающей запятой  11.0 / 4.0 #=> 2.75 Вооот... Так гораздо лучше @@ -59,14 +59,22 @@ filename: learnpython-ru.py  7 % 3 # => 1  # Возведение в степень -2 ** 4 # => 16 +2**4 # => 16  # Приоритет операций указывается скобками  (1 + 3) * 2 #=> 8 -# Логические (булевы) значения являются примитивами -True -False +# Логические операторы +# Обратите внимание: ключевые слова «and» и «or» чувствительны к регистру букв +True and False #=> False +False or True #=> True + +# Обратите внимание, что логические операторы используются и с целыми числами +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True  # Для отрицания используется ключевое слово not  not True #=> False @@ -86,7 +94,7 @@ not False #=> True  2 <= 2 #=> True  2 >= 2 #=> True -# Сравнения могут быть соединены в цепь! +# Сравнения могут быть записаны цепочкой!  1 < 2 < 3 #=> True  2 < 3 < 2 #=> False @@ -94,9 +102,12 @@ not False #=> True  "Это строка."  'Это тоже строка.' -# И строки тоже могут складываться! +# И строки тоже можно складывать!  "Привет " + "мир!" #=> "Привет мир!" +# ... или умножать +"Привет" * 3  # => "ПриветПриветПривет" +  # Со строкой можно работать, как со списком символов  "Это строка"[0] #=> 'Э' @@ -122,7 +133,7 @@ None is None  #=> True  # очень полезен при работе с примитивными типами, но   # зато просто незаменим при работе с объектами. -# None, 0, и пустые строки/списки равны False. +# None, 0 и пустые строки/списки равны False.  # Все остальные значения равны True  0 == False  #=> True  "" == False #=> True @@ -132,12 +143,14 @@ None is None  #=> True  ## 2. Переменные и коллекции  #################################################### -# У Python есть функция Print, доступная в версиях 2.7 и 3, -print("Я Python. Приятно познакомиться!") -# ...и старый оператор print, доступный в версиях 2.x, но удалённый в версии 3. -print "И я тоже Python!" +# В Python есть оператор print, доступный в версиях 2.x, но удалённый в версии 3 +print "Я Python. Приятно познакомиться!" +# В Python также есть функция print(), доступная в версиях 2.7 и 3, +# Но для версии 2.7 нужно добавить следующий импорт модуля (раскомментируйте)): +# from __future__ import print_function +print("Я тоже Python! ") -# Необязательно объявлять переменные перед их инициализацией. +# Объявлять переменные перед инициализацией не нужно.  some_var = 5    # По соглашению используется нижний_регистр_с_подчёркиваниями  some_var #=> 5 @@ -151,7 +164,7 @@ some_other_var  # Выбрасывает ошибку именования  # Списки хранят последовательности  li = [] -# Можно сразу начать с заполненным списком +# Можно сразу начать с заполненного списка  other_li = [4, 5, 6]  # Объекты добавляются в конец списка методом append @@ -166,13 +179,17 @@ li.append(3)    # [1, 2, 4, 3].  # Обращайтесь со списком, как с обычным массивом  li[0] #=> 1 +# Присваивайте новые значения уже инициализированным индексам с помощью = +li[0] = 42 +li[0]  # => 42 +li[0] = 1  # Обратите внимание: возвращаемся на исходное значение  # Обратимся к последнему элементу  li[-1] #=> 3  # Попытка выйти за границы массива приведёт к ошибке индекса  li[4] # Выдаёт IndexError -# Можно обращаться к диапазону, используя "кусочный синтаксис" (slice syntax) +# Можно обращаться к диапазону, используя так называемые срезы  # (Для тех, кто любит математику, это называется замкнуто-открытый интервал).  li[1:3] #=> [2, 4]  # Опускаем начало @@ -183,14 +200,15 @@ li[:3] #=> [1, 2, 4]  li[::2]   # =>[1, 4]  # Переворачиваем список  li[::-1]   # => [3, 4, 2, 1] -# Используйте сочетания всего вышеназванного для выделения более сложных кусков +# Используйте сочетания всего вышеназванного для выделения более сложных срезов  # li[начало:конец:шаг]  # Удаляем произвольные элементы из списка оператором del -del li[2] # [1, 2, 3] +del li[2] # li теперь [1, 2, 3] -# Вы можете складывать списки +# Вы можете складывать, или, как ещё говорят, конкатенировать списки  li + other_li #=> [1, 2, 3, 4, 5, 6]  — Замечание: li и other_li не изменяются +# Обратите внимание: значения li и other_li при этом не изменились.  # Объединять списки можно методом extend  li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6] @@ -226,7 +244,8 @@ empty_dict = {}  # Вот так описывается предзаполненный словарь  filled_dict = {"one": 1, "two": 2, "three": 3} -# Значения ищутся по ключу с помощью оператора [] +# Значения извлекаются так же, как из списка, с той лишь разницей, +# что индекс — у словарей он называется ключом — не обязан быть числом  filled_dict["one"] #=> 1  # Можно получить все ключи в виде списка с помощью метода keys @@ -245,24 +264,33 @@ filled_dict.values() #=> [3, 2, 1]  # Попытка получить значение по несуществующему ключу выбросит ошибку ключа  filled_dict["four"] # KeyError -# Чтобы избежать этого, используйте метод get +# Чтобы избежать этого, используйте метод get()  filled_dict.get("one") #=> 1  filled_dict.get("four") #=> None  # Метод get также принимает аргумент по умолчанию, значение которого будет  # возвращено при отсутствии указанного ключа  filled_dict.get("one", 4) #=> 1  filled_dict.get("four", 4) #=> 4 +# Обратите внимание, что filled_dict.get("four") всё ещё => None +# (get не устанавливает значение элемента словаря) + +# Присваивайте значение ключам так же, как и в списках +filled_dict["four"] = 4  # теперь filled_dict["four"] => 4 -# Метод setdefault вставляет пару ключ-значение, только если такого ключа нет +# Метод setdefault вставляет() пару ключ-значение, только если такого ключа нет  filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5  filled_dict.setdefault("five", 6) #filled_dict["five"] по-прежнему возвращает 5  # Множества содержат... ну, в общем, множества +# (которые похожи на списки, только в них не может быть дублирующихся элементов)  empty_set = set()  # Инициализация множества набором значений  some_set = set([1,2,2,3,4]) # some_set теперь равно set([1, 2, 3, 4]) +# Порядок сортировки не гарантируется, хотя иногда они выглядят отсортированными +another_set = set([4, 3, 2, 2, 1])  # another_set теперь set([1, 2, 3, 4]) +  # Начиная с Python 2.7, вы можете использовать {}, чтобы объявить множество  filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} @@ -345,7 +373,7 @@ try:      # Чтобы выбросить ошибку, используется raise      raise IndexError("Это ошибка индекса")  except IndexError as e: -    # pass это просто отсутствие оператора. Обычно здесь происходит +    # pass — это просто отсутствие оператора. Обычно здесь происходит      # восстановление после ошибки.      pass  except (TypeError, NameError): @@ -362,7 +390,7 @@ else:   # Необязательное выражение. Должно след  # Используйте def для создания новых функций  def add(x, y):      print("x равен %s, а y равен %s" % (x, y)) -    return x + y    # Возвращайте результат выражением return +    return x + y    # Возвращайте результат с помощью ключевого слова return  # Вызов функции с аргументами  add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвращает 11 @@ -370,15 +398,17 @@ add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвр  # Другой способ вызова функции — вызов с именованными аргументами  add(y=6, x=5)   # Именованные аргументы можно указывать в любом порядке. -# Вы можете определить функцию, принимающую изменяемое число аргументов +# Вы можете определить функцию, принимающую переменное число аргументов, +# которые будут интерпретированы как кортеж, если вы не используете *  def varargs(*args):      return args  varargs(1, 2, 3) #=> (1,2,3) -# А также можете определить функцию, принимающую изменяемое число -# именованных аргументов +# А также можете определить функцию, принимающую переменное число +# именованных аргументов, которые будут интерпретированы как словарь, +# если вы не используете **  def keyword_args(**kwargs):      return kwargs @@ -396,13 +426,21 @@ all_the_args(1, 2, a=3, b=4) выводит:  """  # Вызывая функции, можете сделать наоборот! -# Используйте символ * для передачи кортежей и ** для передачи словарей +# Используйте символ * для распаковки кортежей и ** для распаковки словарей  args = (1, 2, 3, 4)  kwargs = {"a": 3, "b": 4}  all_the_args(*args) # эквивалентно foo(1, 2, 3, 4)  all_the_args(**kwargs) # эквивалентно foo(a=3, b=4)  all_the_args(*args, **kwargs) # эквивалентно foo(1, 2, 3, 4, a=3, b=4) +# вы можете передавать переменное число позиционных или именованных аргументов +# другим функциям, которые их принимают, распаковывая их с помощью +# * или ** соответственно +def pass_all_the_args(*args, **kwargs): +    all_the_args(*args, **kwargs) +    print varargs(*args) +    print keyword_args(**kwargs) +  # Область определения функций  x = 5 @@ -420,7 +458,7 @@ def setGlobalX(num):  setX(43)  setGlobalX(6) -# В Python есть функции первого класса +# В Python функции — «объекты первого класса»  def create_adder(x):      def adder(y):          return x + y @@ -514,6 +552,9 @@ from math import *  # Можете сокращать имена модулей  import math as m  math.sqrt(16) == m.sqrt(16) #=> True +# Вы также можете убедиться, что функции эквивалентны +from math import sqrt +math.sqrt == m.sqrt == sqrt  # => True  # Модули в Python — это обычные Python-файлы. Вы  # можете писать свои модули и импортировать их. Название @@ -544,7 +585,7 @@ def double_numbers(iterable):  # мы используем подчёркивание в конце  xrange_ = xrange(1, 900000000) -# Будет удваивать все числа, пока результат не будет >= 30 +# Будет удваивать все числа, пока результат не превысит 30  for i in double_numbers(xrange_):      print(i)      if i >= 30: diff --git a/ru-ru/python3-ru.html.markdown b/ru-ru/python3-ru.html.markdown index 637c0157..fd95c876 100644 --- a/ru-ru/python3-ru.html.markdown +++ b/ru-ru/python3-ru.html.markdown @@ -10,7 +10,7 @@ filename: learnpython3-ru.py  ---  Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из -самых популярных языков. Я люблю его за понятный и доходчивый синтаксис  — это +самых популярных языков. Я влюбился в Python за понятный и доходчивый синтаксис  — это  почти что исполняемый псевдокод.  С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh) @@ -56,7 +56,7 @@ filename: learnpython3-ru.py  7 % 3 # => 1  # Возведение в степень -2 ** 4 # => 16 +2**4 # => 16  # Приоритет операций указывается скобками  (1 + 3) * 2 #=> 8 @@ -69,6 +69,18 @@ False  not True #=> False  not False #=> True +# Логические операторы +# Обратите внимание: ключевые слова «and» и «or» чувствительны к регистру букв +True and False #=> False +False or True #=> True + +# Обратите внимание, что логические операторы используются и с целыми числами +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True +  # Равенство — это ==  1 == 1 #=> True  2 == 1 #=> False @@ -91,7 +103,7 @@ not False #=> True  "Это строка."  'Это тоже строка.' -# И строки тоже могут складываться! Хотя лучше этого не делайте. +# И строки тоже могут складываться! Хотя лучше не злоупотребляйте этим.  "Привет " + "мир!" #=> "Привет мир!"  # Со строкой можно работать, как со списком символов @@ -134,10 +146,10 @@ bool({}) #=> False  ## 2. Переменные и коллекции  #################################################### -# У Python есть функция Print +# В Python есть функция Print  print("Я Python. Приятно познакомиться!") -# Необязательно объявлять переменные перед их инициализацией. +# Объявлять переменные перед инициализацией не нужно.  # По соглашению используется нижний_регистр_с_подчёркиваниями  some_var = 5  some_var #=> 5 @@ -149,7 +161,7 @@ some_unknown_var  # Выбрасывает ошибку именования  # Списки хранят последовательности  li = [] -# Можно сразу начать с заполненным списком +# Можно сразу начать с заполненного списка  other_li = [4, 5, 6]  # Объекты добавляются в конец списка методом append @@ -170,7 +182,7 @@ li[-1] #=> 3  # Попытка выйти за границы массива приведёт к ошибке индекса  li[4] # Выдаёт IndexError -# Можно обращаться к диапазону, используя "кусочный синтаксис" (slice syntax) +# Можно обращаться к диапазону, используя так называемые срезы  # (Для тех, кто любит математику, это называется замкнуто-открытый интервал).  li[1:3] #=> [2, 4]  # Опускаем начало @@ -181,13 +193,14 @@ li[:3] #=> [1, 2, 4]  li[::2]   # =>[1, 4]  # Переворачиваем список  li[::-1]   # => [3, 4, 2, 1] -# Используйте сочетания всего вышеназванного для выделения более сложных кусков +# Используйте сочетания всего вышеназванного для выделения более сложных срезов  # li[начало:конец:шаг]  # Удаляем произвольные элементы из списка оператором del  del li[2] # [1, 2, 3] -# Вы можете складывать списки +# Вы можете складывать, или, как ещё говорят, конкатенировать списки +# Обратите внимание: значения li и other_li при этом не изменились.  li + other_li #=> [1, 2, 3, 4, 5, 6]  — Замечание: li и other_li не изменяются  # Объединять списки можно методом extend @@ -224,10 +237,11 @@ empty_dict = {}  # Вот так описывается предзаполненный словарь  filled_dict = {"one": 1, "two": 2, "three": 3} -# Значения ищутся по ключу с помощью оператора [] +# Значения извлекаются так же, как из списка, с той лишь разницей, +# что индекс — у словарей он называется ключом — не обязан быть числом  filled_dict["one"] #=> 1 -# Все значения в виде списка получаются с помощью метода keys().  +# Все ключи в виде списка получаются с помощью метода keys().   # Его вызов нужно обернуть в list(), так как обратно мы получаем  # итерируемый объект, о которых поговорим позднее.  list(filled_dict.keys())   # => ["three", "two", "one"] @@ -247,7 +261,7 @@ list(filled_dict.values())   # => [3, 2, 1]  # Попытка получить значение по несуществующему ключу выбросит ошибку ключа  filled_dict["four"] # KeyError -# Чтобы избежать этого, используйте метод get +# Чтобы избежать этого, используйте метод get()  filled_dict.get("one") #=> 1  filled_dict.get("four") #=> None  # Метод get также принимает аргумент по умолчанию, значение которого будет @@ -259,6 +273,10 @@ filled_dict.get("four", 4) #=> 4  filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5  filled_dict.setdefault("five", 6) #filled_dict["five"] по-прежнему возвращает 5 +# Добавление элементов в словарь +filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4} +#filled_dict["four"] = 4  # Другой способ добавления элементов +  # Удаляйте ключи из словаря с помощью оператора del  del filled_dict["one"]  # Удаляет ключ «one» из словаря @@ -345,7 +363,7 @@ try:      # Чтобы выбросить ошибку, используется raise      raise IndexError("Это ошибка индекса")  except IndexError as e: -    # pass это просто отсутствие оператора. Обычно здесь происходит +    # pass — это просто отсутствие оператора. Обычно здесь происходит      # восстановление после ошибки.      pass  except (TypeError, NameError): @@ -393,7 +411,7 @@ list(filled_dict.keys())  #=> Возвращает ["one", "two", "three"]  # Используйте def для создания новых функций  def add(x, y):      print("x равен %s, а y равен %s" % (x, y)) -    return x + y    # Возвращайте результат выражением return +    return x + y    # Возвращайте результат с помощью ключевого слова return  # Вызов функции с аргументами  add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвращает 11 @@ -401,14 +419,14 @@ add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвр  # Другой способ вызова функции — вызов с именованными аргументами  add(y=6, x=5)   # Именованные аргументы можно указывать в любом порядке. -# Вы можете определить функцию, принимающую изменяемое число аргументов +# Вы можете определить функцию, принимающую переменное число аргументов  def varargs(*args):      return args  varargs(1, 2, 3) #=> (1,2,3) -# А также можете определить функцию, принимающую изменяемое число +# А также можете определить функцию, принимающую переменное число  # именованных аргументов  def keyword_args(**kwargs):      return kwargs @@ -427,7 +445,7 @@ all_the_args(1, 2, a=3, b=4) выводит:  """  # Вызывая функции, можете сделать наоборот! -# Используйте символ * для передачи кортежей и ** для передачи словарей +# Используйте символ * для распаковки кортежей и ** для распаковки словарей  args = (1, 2, 3, 4)  kwargs = {"a": 3, "b": 4}  all_the_args(*args) # эквивалентно foo(1, 2, 3, 4) @@ -451,7 +469,7 @@ def setGlobalX(num):  setX(43)  setGlobalX(6) -# В Python функции — «объекты первого класса». Это означает, что их можно использовать наравне с любыми другими значениями +# В Python функции — «объекты первого класса»  def create_adder(x):      def adder(y):          return x + y diff --git a/ru-ru/swift-ru.html.markdown b/ru-ru/swift-ru.html.markdown new file mode 100644 index 00000000..77987bb3 --- /dev/null +++ b/ru-ru/swift-ru.html.markdown @@ -0,0 +1,589 @@ +--- +language: swift +contributors: +  - ["Grant Timmerman", "http://github.com/grant"] +  - ["Christopher Bess", "http://github.com/cbess"] +  - ["Joey Huang", "http://github.com/kamidox"] +filename: learnswift-ru.swift +translators: +  - ["Dmitry Bessonov", "https://github.com/TheDmitry"] +lang: ru-ru +--- + +Swift - это язык программирования, созданный компанией Apple, для приложений +под iOS и OS X. Разработанный, чтобы сосуществовать с Objective-C и +быть более устойчивым к ошибочному коду, Swift был представлен в 2014 году на +конференции разработчиков Apple, WWDC. Приложения на Swift собираются +с помощью LLVM-компилятора, включенного в Xcode 6+. + +Официальная книга по [языку программирования Swift](https://itunes.apple.com/us/book/swift-programming-language/id881256329) от Apple доступна в iBooks. + +Смотрите еще [начальное руководство](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) Apple, которое содержит полное учебное пособие по Swift. + +```swift +// импорт модуля +import UIKit + +// +// MARK: Основы +// + +// Xcode поддерживает маркеры, чтобы давать примечания своему коду +// и вносить их в список обозревателя (Jump Bar) +// MARK: Метка раздела +// TODO: Сделайте что-нибудь вскоре +// FIXME: Исправьте этот код + +println("Привет, мир") + +// переменные (var), значение которых можно изменить после инициализации +// константы (let), значение которых нельзя изменить после инициализации + +var myVariable = 42 +let øπΩ = "значение" // именование переменной символами unicode +let π = 3.1415926 +let convenience = "Ключевое слово" // контекстное имя переменной +let weak = "Ключевое слово"; let override = "еще ключевое слово" // операторы +                                      // могут быть отделены точкой с запятой +let `class` = "Ключевое слово" // обратные апострофы позволяют использовать +                               // ключевые слова в именовании переменных +let explicitDouble: Double = 70 +let intValue = 0007 // 7 +let largeIntValue = 77_000 // 77000 +let label = "некоторый текст " + String(myVariable) // Приведение типа +let piText = "Pi = \(π), Pi 2 = \(π * 2)" // Вставка переменных в строку + +// Сборка особых значений +// используя ключ -D сборки конфигурации +#if false +    println("Не печатается") +    let buildValue = 3 +#else +    let buildValue = 7 +#endif +println("Значение сборки: \(buildValue)") // Значение сборки: 7 + +/* +    Опционалы - это особенность языка Swift, которая допускает вам сохранять +    `некоторое` или `никакое` значения. + +    Язык Swift требует, чтобы каждое свойство имело значение, поэтому даже nil +    должен быть явно сохранен как опциональное значение. + +    Optional<T> является перечислением. +*/ +var someOptionalString: String? = "опционал" // Может быть nil +// как и выше, только ? - это постфиксный оператор (синтаксический сахар) +var someOptionalString2: Optional<String> = "опционал" + +if someOptionalString != nil { +    // я не nil +    if someOptionalString!.hasPrefix("opt") { +        println("содержит префикс") +    } +     +    let empty = someOptionalString?.isEmpty +} +someOptionalString = nil + +// неявная развертка опциональной переменной +var unwrappedString: String! = "Ожидаемое значение." +// как и выше, только ! - постфиксный оператор (с еще одним синтаксическим сахаром) +var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Ожидаемое значение." + +if let someOptionalStringConstant = someOptionalString { +    // имеется некоторое значение, не nil +    if !someOptionalStringConstant.hasPrefix("ok") { +        // нет такого префикса +    } +} + +// Swift поддерживает сохранение значения любого типа +// AnyObject == id +// В отличие от `id` в Objective-C, AnyObject работает с любым значением (Class, +// Int, struct и т.д.) +var anyObjectVar: AnyObject = 7 +anyObjectVar = "Изменять значение на строку не является хорошей практикой, но возможно." + +/* +    Комментируйте здесь +     +    /* +        Вложенные комментарии тоже поддерживаются +    */ +*/ + +// +// MARK: Коллекции +// + +/* +    Массив (Array) и словарь (Dictionary) являются структурами (struct). Так +    `let` и `var` также означают, что они изменяются (var) или не изменяются (let) +    при объявлении переменных этих типов. +*/ + +// Массив +var shoppingList = ["сом", "вода", "лимоны"] +shoppingList[1] = "бутылка воды" +let emptyArray = [String]() // let == неизменный +let emptyArray2 = Array<String>() // как и выше +var emptyMutableArray = [String]() // var == изменяемый + + +// Словарь +var occupations = [ +    "Malcolm": "Капитан", +    "kaylee": "Техник" +] +occupations["Jayne"] = "Связи с общественностью" +let emptyDictionary = [String: Float]() // let == неизменный +let emptyDictionary2 = Dictionary<String, Float>() // как и выше +var emptyMutableDictionary = [String: Float]() // var == изменяемый + + +// +// MARK: Поток управления +// + +// цикл for для массива +let myArray = [1, 1, 2, 3, 5] +for value in myArray { +    if value == 1 { +        println("Один!") +    } else { +        println("Не один!") +    } +} + +// цикл for для словаря +var dict = ["один": 1, "два": 2] +for (key, value) in dict { +    println("\(key): \(value)") +} + +// цикл for для диапазона чисел +for i in -1...shoppingList.count { +    println(i) +} +shoppingList[1...2] = ["бифштекс", "орехи пекан"] +// используйте ..< для исключения последнего числа + +// цикл while +var i = 1 +while i < 1000 { +    i *= 2 +} + +// цикл do-while +do { +    println("привет") +} while 1 == 2 + +// Переключатель +// Очень мощный оператор, представляйте себе операторы `if` с синтаксическим +// сахаром +// Они поддерживают строки, объекты и примитивы (Int, Double, etc) +let vegetable = "красный перец" +switch vegetable { +case "сельдерей": +    let vegetableComment = "Добавьте немного изюма, имитируя муравьев на бревнышке." +case "огурец", "кресс-салат": +    let vegetableComment = "Было бы неплохо сделать бутерброд с чаем." +case let localScopeValue where localScopeValue.hasSuffix("перец"): +    let vegetableComment = "Это острый \(localScopeValue)?" +default: // обязательный (чтобы предусмотреть все возможные вхождения) +    let vegetableComment = "В супе все овощи вкусные." +} + + +// +// MARK: Функции +// + +// Функции являются типом первого класса, т.е. они могут быть вложены в функциях +// и могут передаваться между собой + +// Функция с документированным заголовком Swift (формат reStructedText) + +/** +    Операция приветствия + +    - Маркер в документировании +    - Еще один маркер в документации + +    :param: name - это имя +    :param: day - это день +    :returns: Строка, содержащая значения name и day. +*/ +func greet(name: String, day: String) -> String { +    return "Привет \(name), сегодня \(day)." +} +greet("Боб", "вторник") + +// как и выше, кроме обращения параметров функции +func greet2(#requiredName: String, externalParamName localParamName: String) -> String { +    return "Привет \(requiredName), сегодня \(localParamName)" +} +greet2(requiredName:"Иван", externalParamName: "воскресенье") + +// Функция, которая возвращает множество элементов в кортеже +func getGasPrices() -> (Double, Double, Double) { +    return (3.59, 3.69, 3.79) +} +let pricesTuple = getGasPrices() +let price = pricesTuple.2 // 3.79 +// Пропускайте значения кортежей с помощью подчеркивания _ +let (_, price1, _) = pricesTuple // price1 == 3.69 +println(price1 == pricesTuple.1) // вывод: true +println("Цена газа: \(price)") + +// Переменное число аргументов +func setup(numbers: Int...) { +    // это массив +    let number = numbers[0] +    let argCount = numbers.count +} + +// Передача и возврат функций +func makeIncrementer() -> (Int -> Int) { +    func addOne(number: Int) -> Int { +        return 1 + number +    } +    return addOne +} +var increment = makeIncrementer() +increment(7) + +// передача по ссылке +func swapTwoInts(inout a: Int, inout b: Int) { +    let tempA = a +    a = b +    b = tempA +} +var someIntA = 7 +var someIntB = 3 +swapTwoInts(&someIntA, &someIntB) +println(someIntB) // 7 + + +// +// MARK: Замыкания +// +var numbers = [1, 2, 6] + +// Функции - это частный случай замыканий ({}) + +// Пример замыкания. +// `->` отделяет аргументы и возвращаемый тип +// `in` отделяет заголовок замыкания от тела замыкания +numbers.map({ +    (number: Int) -> Int in +    let result = 3 * number +    return result +}) + +// Когда тип известен, как и выше, мы можем сделать так +numbers = numbers.map({ number in 3 * number }) +// Или даже так +//numbers = numbers.map({ $0 * 3 }) + +print(numbers) // [3, 6, 18] + +// Хвостовое замыкание +numbers = sorted(numbers) { $0 > $1 } + +print(numbers) // [18, 6, 3] + +// Суперсокращение, поскольку оператор < выполняет логический вывод типов + +numbers = sorted(numbers, < ) + +print(numbers) // [3, 6, 18] + +// +// MARK: Структуры +// + +// Структуры и классы имеют очень похожие характеристики +struct NamesTable { +    let names = [String]() +     +    // Пользовательский индекс +    subscript(index: Int) -> String { +        return names[index] +    } +} + +// У структур автогенерируемый (неявно) инициализатор +let namesTable = NamesTable(names: ["Me", "Them"]) +let name = namesTable[1] +println("Name is \(name)") // Name is Them + +// +// MARK: Классы +// + +// Классы, структуры и их члены имеют трехуровневый контроль доступа +// Уровни: internal (по умолчанию), public, private + +public class Shape { +    public func getArea() -> Int { +        return 0; +    } +} + +// Все методы и свойства класса являются открытыми (public). +// Если вам необходимо содержать только данные +// в структурированном объекте, вы должны использовать `struct` + +internal class Rect: Shape { +    var sideLength: Int = 1 +     +    // Пользовательский сеттер и геттер +    private var perimeter: Int { +        get { +            return 4 * sideLength +        } +        set { +            // `newValue` - неявная переменная, доступная в сеттере +            sideLength = newValue / 4 +        } +    } +     +    // Ленивая загрузка свойства +    // свойство subShape остается равным nil (неинициализированным), +    // пока не вызовется геттер +    lazy var subShape = Rect(sideLength: 4) +     +    // Если вам не нужны пользовательские геттеры и сеттеры, +    // но все же хотите запустить код перед и после вызовов геттера или сеттера +    // свойств, вы можете использовать `willSet` и `didSet` +    var identifier: String = "defaultID" { +        // аргумент у `willSet` будет именем переменной для нового значения +        willSet(someIdentifier) { +            print(someIdentifier) +        } +    } +     +    init(sideLength: Int) { +        self.sideLength = sideLength +        // последним всегда вызывается super.init, когда init с параметрами +        super.init() +    } +     +    func shrink() { +        if sideLength > 0 { +            --sideLength +        } +    } +     +    override func getArea() -> Int { +        return sideLength * sideLength +    } +} + +// Простой класс `Square` наследует `Rect` +class Square: Rect { +    convenience init() { +        self.init(sideLength: 5) +    } +} + +var mySquare = Square() +print(mySquare.getArea()) // 25 +mySquare.shrink() +print(mySquare.sideLength) // 4 + +// преобразование объектов +let aShape = mySquare as Shape + +// сравнение экземпляров, в отличие от ==, которая проверяет эквивалентность +if mySquare === mySquare { +    println("Ага, это mySquare") +} + +// Опциональная инициализация (init) +class Circle: Shape { +    var radius: Int +    override func getArea() -> Int { +        return 3 * radius * radius +    } +     +    // Поместите постфиксный знак вопроса после `init` - это и будет опциональная инициализация, +    // которая может вернуть nil +    init?(radius: Int) { +        self.radius = radius +        super.init() +         +        if radius <= 0 { +            return nil +        } +    } +} + +var myCircle = Circle(radius: 1) +println(myCircle?.getArea())    // Optional(3) +println(myCircle!.getArea())    // 3 +var myEmptyCircle = Circle(radius: -1) +println(myEmptyCircle?.getArea())    // "nil" +if let circle = myEmptyCircle { +    // не будет выполняться, поскольку myEmptyCircle равен nil +    println("circle не nil") +} + + +// +// MARK: Перечисления +// + +// Перечисления могут быть определенного или своего типа. +// Они могут содержать методы подобно классам. + +enum Suit { +    case Spades, Hearts, Diamonds, Clubs +    func getIcon() -> String { +        switch self { +        case .Spades: return "♤" +        case .Hearts: return "♡" +        case .Diamonds: return "♢" +        case .Clubs: return "♧" +        } +    } +} + +// Значения перечислений допускают сокращенный синтаксис, нет необходимости +// указывать тип перечисления, когда переменная объявляется явно +var suitValue: Suit = .Hearts + +// Нецелочисленные перечисления требуют прямого указания значений +enum BookName: String { +    case John = "Иоанн" +    case Luke = "Лука" +} +println("Имя: \(BookName.John.rawValue)") + +// Перечисление (enum) со связанными значениями +enum Furniture { +    // Связать с типом Int +    case Desk(height: Int) +    // Связать с типами String и Int +    case Chair(String, Int) +     +    func description() -> String { +        switch self { +        case .Desk(let height): +            return "Письменный стол высотой \(height) см." +        case .Chair(let brand, let height): +            return "Стул марки \(brand) высотой \(height) см." +        } +    } +} + +var desk: Furniture = .Desk(height: 80) +println(desk.description())     // "Письменный стол высотой 80 см." +var chair = Furniture.Chair("Foo", 40) +println(chair.description())    // "Стул марки Foo высотой 40 см." + + +// +// MARK: Протоколы +// + +// `protocol` может потребовать, чтобы у соответствующих типов +// были определенные свойства экземпляра, методы экземпляра, тип методов, +// операторы и индексы. + +protocol ShapeGenerator { +    var enabled: Bool { get set } +    func buildShape() -> Shape +} + +// Протоколы, объявленные с @objc, допускают необязательные функции, +// которые позволяют вам проверять на соответствие +@objc protocol TransformShape { +    optional func reshaped() +    optional func canReshape() -> Bool +} + +class MyShape: Rect { +    var delegate: TransformShape? +     +    func grow() { +        sideLength += 2 +        // Размещайте знак вопроса перед опционным свойством, методом +        // или индексом, чтобы не учитывать nil-значение и возвратить nil +        // вместо выбрасывания ошибки выполнения (т.н. "опционная цепочка") +        if let allow = self.delegate?.canReshape?() { +            // проверка делегата на выполнение метода +            self.delegate?.reshaped?() +        } +    } +} + + +// +// MARK: Прочее +// + +// `extension`s: Добавляет расширенный функционал к существующему типу + +// Класс Square теперь "соответствует" протоколу `Printable` +extension Square: Printable { +    var description: String { +        return "Площадь: \(self.getArea()) - ID: \(self.identifier)" +    } +} + +println("Объект Square: \(mySquare)") + +// Вы также можете расширить встроенные типы +extension Int { +    var customProperty: String { +        return "Это \(self)" +    } +     +    func multiplyBy(num: Int) -> Int { +        return num * self +    } +} + +println(7.customProperty) // "Это 7" +println(14.multiplyBy(3)) // 42 + +// Обобщения: Подобно языкам Java и C#. Используйте ключевое слово `where`, +// чтобы определить условия обобщений. + +func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { +    for (index, value) in enumerate(array) { +        if value == valueToFind { +            return index +        } +    } +    return nil +} +let foundAtIndex = findIndex([1, 2, 3, 4], 3) +println(foundAtIndex == 2) // вывод: true + +// Операторы: +// Пользовательские операторы могут начинаться с символов: +//      / = - + * % < > ! & | ^ . ~ +// или +// Unicode- знаков математики, символов, стрелок, декорации и линий/кубов, +// нарисованных символов. +prefix operator !!! {} + +// Префиксный оператор, который утраивает длину стороны, когда используется +prefix func !!! (inout shape: Square) -> Square { +    shape.sideLength *= 3 +    return shape +} + +// текущее значение +println(mySquare.sideLength) // 4 + +// Используя пользовательский оператор !!!, изменится длина стороны +// путем увеличения размера в 3 раза +!!!mySquare +println(mySquare.sideLength) // 12 +``` diff --git a/ru-ru/xml-ru.html.markdown b/ru-ru/xml-ru.html.markdown new file mode 100644 index 00000000..b0096b75 --- /dev/null +++ b/ru-ru/xml-ru.html.markdown @@ -0,0 +1,130 @@ +--- +language: xml +filename: learnxml-ru.xml +contributors: +  - ["João Farias", "https://github.com/JoaoGFarias"] +translators: +  - ["Dmitry Bessonov", "https://github.com/TheDmitry"] +lang: ru-ru +--- + +XML - это язык разметки, предназначенный для хранения и передачи данных. + +В отличие от HTML, XML не определяет, как отображать или форматировать данные, он только содержит их. + +* XML-Синтаксис + +```xml +<!-- Комментарии в XML выглядят вот так --> + +<?xml version="1.0" encoding="UTF-8"?> +<bookstore> +  <book category="КУЛИНАРИЯ"> +    <title lang="ru">Итальянская кухня каждый день</title> +    <author>Giada De Laurentiis</author> +    <year>2005</year> +    <price>30.00</price> +  </book> +  <book category="ДЕТИ"> +    <title lang="ru">Гарри Поттер</title> +    <author>Дж. К. Роулинг</author> +    <year>2005</year> +    <price>29.99</price> +  </book> +  <book category="ВСЕМИРНАЯ ПАУТИНА"> +    <title lang="ru">Изучаем XML</title> +    <author>Эрик Рэй</author> +    <year>2003</year> +    <price>39.95</price> +  </book> +</bookstore> + +<!-- Вышеописанный документ - типичный XML-файл. +  Он начинается с определения, объявляющего о некоторых метаданных (необязательно). +   +  XML использует древовидную структуру. У вышеописанного документа +  корневой узел - 'bookstore', который содержит три дочерних узла - все 'book'-узлы. +  Такие узлы содержат еще дочерние узлы и т.д. +   +  Узлы создаются с помощью открывающих/закрывающих тегов, +  а дочерние узлы - это узлы между открывающимися и закрывающимися тегами.--> + + +<!-- XML содержит в себе два типа данных: +  1 - Атрибуты -> Это метаданные узлов. +      Обычно XML-парсер использует эту информацию, чтобы хранить свойства данных. +      Атрибут изображается путем вписывания его в скобки в пределах открытого тега +  2 - Элементы -> Это чистые данные. +      Это то, что парсер извлечет из XML-файла. +      Элементы идут между открытыми и закрытыми тегами без скобок. --> +       +   +<!-- Ниже элемент с двумя атрибутами --> +<file type="gif" id="4293">компьютер.gif</file> + + +``` + +* Хорошо отформатированный документ x Проверка достоверности + +XML-документ хорошо отформатирован, если он синтаксически верный. +Впрочем, в документ возможно ввести больше ограничений, +используя определения документа, вроде DTD и XML-схемы. + +XML-документ, который следует описанию документа, называется корректным, +относительно этого документа.  + +С таким инструментом вы можете проверить XML-данные вне логики приложения. + +```xml + +<!-- Ниже вы можете увидеть упрощенную версию документа книжного магазина, +  с дополнением DTD-определения.--> + +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE note SYSTEM "Bookstore.dtd"> +<bookstore> +  <book category="КУЛИНАРИЯ"> +    <title >Итальянская кухня каждый день</title> +    <price>30.00</price> +  </book> +</bookstore> + +<!-- Этот DTD может быть чем-то вроде:--> + +<!DOCTYPE note +[ +<!ELEMENT bookstore (book+)> +<!ELEMENT book (title,price)> +<!ATTLIST book category CDATA "Литература"> +<!ELEMENT title (#PCDATA)> +<!ELEMENT price (#PCDATA)> +]> + + +<!-- DTD начинается с объявления. +  Затем объявляется корневой узел, требующий 1 или более дочерних узлов 'book'. +  Каждый 'book' должен содержать точно один 'title' и 'price', и атрибут, +  называемый 'category', со значением "Литература" по умолчанию. +  Узлы 'title' и 'price' содержат анализируемые символьные данные.--> + +<!-- DTD может быть объявлен в самом XML-файле.--> + +<?xml version="1.0" encoding="UTF-8"?> + +<!DOCTYPE note +[ +<!ELEMENT bookstore (book+)> +<!ELEMENT book (title,price)> +<!ATTLIST book category CDATA "Литература"> +<!ELEMENT title (#PCDATA)> +<!ELEMENT price (#PCDATA)> +]> + +<bookstore> +  <book category="КУЛИНАРИЯ"> +    <title >Итальянская кухня каждый день</title> +    <price>30.00</price> +  </book> +</bookstore> +```  | 
