-
Notifications
You must be signed in to change notification settings - Fork 28
jpath
jpath
— это язык запросов для доступа к различным элементам javascript-дерева.
В общем-то, это аналог xpath
, с поправкой на javascript синтаксис.
Кроме того, из-за естественных ограничений javascript-объектов, в нем нет некоторых возможностей (например, осей).
Для простоты можно считать, что речь идет про json
.
Т.е. про древовидную структуру, построенную из javascript'овых объектов, массиов и "скаляров".
К сожалению (или к счастью), json
намного беднее xml
, так что приходится идти на некоторые компромиссы.
Однозначного соответствия между xml-документами и js-документами нет. Более-менее, можно для каждого js-объекта построить соотвествующий ему xml-фрагмент (не всегда xml-документ).
Вот простейший объект:
{
id: 1,
title: "first",
disabled: true
}
Ему соотвествует вот такой xml-фрагмент:
<id>1</id>
<title>first</title>
<disabled/>
Важно. Это не xml-документ, у него нет корневого элемента. Просто потому, что неизвестно какое имя может быть у этого элемента -- в самом js-объекте никаких следов этого имени нет, но оно может быть определено из контекста, в котором находится этот js-объект:
{
id: 42,
data: {
id: 1,
title: "first",
disabled: true
}
}
Здесь внешний объект по-прежнему не имеет имени, но внутреннему объекту можно назначить имя data
:
<id>42</id>
<data>
<id>1</id>
<title>first</title>
<disabled/>
</data>
Т.е., грубо говоря, "полноценный" xml-документ получается из вот такой (бессмысленной в javascript'е) конструкции:
data: {
id: 1,
title: "first",
disabled: true
}
Массив:
[ 1, 2, 3 ]
Соответствующий ему xml-фрагмент:
<item>1</item>
<item>2</item>
<item>3</item>
Т.е. каждый элемент массива — это отдельный xml-элемент (сам массив при этом своего собственного элемента не имеет).
При этом имя этого элемента либо (как и для объектов) определяется из контекста,
либо же назначается равным item
для безымянных массивов.
{
id: 42,
data: [ 1, 2, 3 ]
}
<id>42</id>
<data>1</data>
<data>2</data>
<data>3</data>
Более развесистый пример:
{
data: [
{
id: 1,
title: "first",
disabled: true
},
{
id: 2,
title: "second"
},
{
id: 3,
title: "third"
}
]
}
Соответствующий xml:
<data>
<id>1</id>
<title>first</title>
<disabled/>
</data>
<data>
<id>2</id>
<title>second</title>
</data>
<data>
<id>3</id>
<title>third</title>
</data>
В обычном json
помимо объектов и массивов могут встречаться строки, числа, true, false и null.
В нашем js-дереве false и null не используются (непонятно, чему их сопоставлять):
{
id: "2345673457568956867",
count: 42,
title: "Hello, World",
disabled: true
}
<id>2345673457568956867</id>
<count>42</count>
<title>Hello, World</title>
<disabled/>
Важно. Не стоит забывать, что в javascript'е нет целых 64-битных чисел, поэтому иногда лучше использовать строки. Например, для длинных цифровых id-шников.
В отличие от xpath
, где бывают абсолютные и относительные пути, все jpath
всегда относительные.
Простые примеры и xpath-аналоги:
.foo foo
.foo.bar foo/bar
. .
.. ..
... ../..
..foo ../foo
..foo..bar ../foo/../bar
.foo.* foo/*
..* ../*
.*.* */*
Все jpath
всегда начинаются с символа .
Как и в xpath
, в jpath
существуют предикаты, позволяющие уточнить выборку:
.items.item [ .disable ] items/item[ disabled ]
.items.item[ .count > 0 && .count < 5 ] items/item[ count > 0 and count < 5 ]
Соответствие jpath
и xpath
операторов:
a | b a | b
a + b a + b // Числовое сложение только!
a - b a - b
a * b a * b
a / b a div b
a % b a mod b
a || b a or b
a && b a and b
!a not(a)
a > b a > b
a >= b a >= b
a < b a < b
a <= b a <= b
a == b a = b
a != b a != b
В xpath
если выражение внутри [...]
является числом, то это не предикат, а индекс.
items/item[42] // выбрать 42-й item.
В jpath
разница между предикатом и индексом определяется немного не так.
Вот для сравнения два jpath:
.items.item[ .index ]
и
index = 42
.items.item[ index ]
Разница между .index
и index
в том, что index
является "абсолютным" выражением в данном контексте.
Т.е. оно не зависит от конкретного item'а. Поэтому это индекс.
.index
зависит от item'а — это предикат (т.е. мы фильтруем все item'а по условию внутри [...]
).