Index: rtemsqual/items.py
===================================================================
--- rtemsqual/items.py	(revision 3b9b2bdfece46ee5e334869692c066a1cfba96f2)
+++ rtemsqual/items.py	(revision 22ec40f5ec8ba636f9dc5442c7025d3ffb0aba68)
@@ -25,8 +25,10 @@
 # POSSIBILITY OF SUCH DAMAGE.
 
+from contextlib import contextmanager
 import os
 import pickle
+import string
 import stat
-from typing import Any, Dict, Iterator, List
+from typing import Any, Callable, Dict, Iterator, List, Mapping, Tuple
 import yaml
 
@@ -34,4 +36,5 @@
 
 ItemMap = Dict[str, "Item"]
+KeyMapper = Callable[["Item", Any, str], Any]
 
 
@@ -108,4 +111,8 @@
 
 
+def _key_error(_item: "Item", _value: Any, _key: str) -> str:
+    raise KeyError
+
+
 class Item:
     """ Objects of this class represent a specification item. """
@@ -123,4 +130,25 @@
         return self._data[name]
 
+    def get(self,
+            key_path: str,
+            prefix: str = "",
+            mapper: KeyMapper = _key_error) -> Any:
+        """ Gets the attribute value corresponding to the key path. """
+        if not os.path.isabs(key_path):
+            key_path = os.path.join(prefix, key_path)
+        key_path = os.path.normpath(key_path)
+        value = self._data
+        for key in key_path.strip("/").split("/"):
+            parts = key.split("[")
+            try:
+                value = value[parts[0]]
+            except KeyError:
+                value = mapper(self, value, parts[0])
+            try:
+                value = value[int(parts[1].split("]")[0])]
+            except IndexError:
+                pass
+        return value
+
     @property
     def uid(self) -> str:
@@ -133,4 +161,6 @@
         item.
         """
+        if abs_or_rel_uid == ".":
+            return self._uid
         if os.path.isabs(abs_or_rel_uid):
             return abs_or_rel_uid
@@ -207,4 +237,64 @@
             self._data = yaml.safe_load(src.read())
             self._data["_file"] = filename
+
+
+class ItemTemplate(string.Template):
+    """ String template for item mapper identifiers. """
+    idpattern = "[a-zA-Z0-9._/-]+:[][a-zA-Z0-9._/-]+(|[a-zA-Z0-9_]+)*"
+
+
+class ItemMapper(Mapping[str, object]):
+    """ Maps identifiers to items and attribute values. """
+    def __init__(self, item: "Item"):
+        self._item = item
+        self._prefix = [""]
+
+    def push_prefix(self, prefix: str) -> None:
+        """ Pushes a key path prefix. """
+        self._prefix.append(prefix)
+
+    def pop_prefix(self) -> None:
+        """ Pops a key path prefix. """
+        self._prefix.pop()
+
+    @contextmanager
+    def prefix(self, prefix: str) -> Iterator[None]:
+        """ Opens a key path prefix context. """
+        self.push_prefix(prefix)
+        yield
+        self.pop_prefix()
+
+    def map(self, identifier: str) -> Tuple[Item, Any]:
+        """
+        Maps an identifier to the corresponding item and attribute value.
+        """
+        parts = identifier.split("|")
+        uid, key_path = parts[0].split(":")
+        if uid == ".":
+            item = self._item
+            prefix = "/".join(self._prefix)
+        else:
+            item = self._item.map(uid)
+            prefix = ""
+        value = item.get(key_path, prefix, self._key_mapper)
+        for func in parts[1:]:
+            value = getattr(self, func)(value)
+        return item, value
+
+    def __getitem__(self, identifier):
+        return self.map(identifier)[1]
+
+    def __iter__(self):
+        raise StopIteration
+
+    def __len__(self):
+        raise AttributeError
+
+    def substitute(self, text: str) -> str:
+        """ Performs a variable substitution using the item mapper. """
+        return ItemTemplate(text).substitute(self)
+
+    def _key_mapper(self, item: Item, value: Any, key: str) -> Any:
+        return getattr(self, key.replace("-", "_"))(item, value)
 
 
Index: rtemsqual/tests/spec-item-cache/d/c.yml
===================================================================
--- rtemsqual/tests/spec-item-cache/d/c.yml	(revision 3b9b2bdfece46ee5e334869692c066a1cfba96f2)
+++ rtemsqual/tests/spec-item-cache/d/c.yml	(revision 22ec40f5ec8ba636f9dc5442c7025d3ffb0aba68)
@@ -3,2 +3,11 @@
   uid: ../p
 v: c
+a:
+  b: e
+  f:
+  - 1
+  - 2
+  - 3
+  - g:
+    - 4
+    - 5
Index: rtemsqual/tests/test_items_item.py
===================================================================
--- rtemsqual/tests/test_items_item.py	(revision 3b9b2bdfece46ee5e334869692c066a1cfba96f2)
+++ rtemsqual/tests/test_items_item.py	(revision 22ec40f5ec8ba636f9dc5442c7025d3ffb0aba68)
@@ -38,4 +38,5 @@
 def test_to_abs_uid():
     item = Item(EmptyCache(), "/x/y", {})
+    assert item.to_abs_uid(".") == "/x/y"
     assert item.to_abs_uid("z") == "/x/z"
     assert item.to_abs_uid("/z") == "/z"
@@ -55,4 +56,22 @@
     assert "x" in item
     assert "a" not in item
+
+
+def test_get():
+    data = {}
+    data["a"] = {"b": "c", "d": [1, 2, 3]}
+    data["x"] = "y"
+    item = Item(EmptyCache(), "z", data)
+    assert item.get("x") == "y"
+    assert item.get("a/d[2]") == 3
+    assert item.get("a/b/../d[0]") == 1
+    assert item.get("/a/b/../d[0]") == 1
+    assert item.get("../d[0]", "a/b") == 1
+    with pytest.raises(KeyError):
+        assert item.get("y")
+    with pytest.raises(KeyError):
+        assert item.get("[")
+    with pytest.raises(ValueError):
+        assert item.get("x[y]")
 
 
Index: rtemsqual/tests/test_items_itemcache.py
===================================================================
--- rtemsqual/tests/test_items_itemcache.py	(revision 3b9b2bdfece46ee5e334869692c066a1cfba96f2)
+++ rtemsqual/tests/test_items_itemcache.py	(revision 22ec40f5ec8ba636f9dc5442c7025d3ffb0aba68)
@@ -29,5 +29,5 @@
 import shutil
 
-from rtemsqual.items import ItemCache
+from rtemsqual.items import ItemCache, ItemMapper, ItemTemplate
 
 
@@ -37,5 +37,5 @@
 
 
-def test_load(tmpdir):
+def _create_spec_and_config(tmpdir):
     config = {}
     cache_dir = os.path.join(tmpdir, "cache")
@@ -45,10 +45,16 @@
     shutil.copytree(spec_src, spec_dst)
     config["paths"] = [os.path.normpath(spec_dst)]
-    ic = ItemCache(config)
+    return config
+
+
+def test_load(tmpdir):
+    config = _create_spec_and_config(tmpdir)
+    item_cache = ItemCache(config)
+    cache_dir = config["cache-directory"]
     assert os.path.exists(os.path.join(cache_dir, "spec", "spec.pickle"))
     assert os.path.exists(os.path.join(cache_dir, "spec", "d", "spec.pickle"))
-    assert ic["/d/c"]["v"] == "c"
-    assert ic["/p"]["v"] == "p"
-    t = ic.top_level
+    assert item_cache["/d/c"]["v"] == "c"
+    assert item_cache["/p"]["v"] == "p"
+    t = item_cache.top_level
     assert len(t) == 1
     p = t["/p"]
@@ -56,12 +62,60 @@
     assert p.map("/p") == p
     assert p.map("p") == p
-    a = ic.all
+    a = item_cache.all
     assert len(a) == 2
     assert a["/p"]["v"] == "p"
     assert a["/d/c"]["v"] == "c"
-    ic2 = ItemCache(config)
-    assert ic2["/d/c"]["v"] == "c"
+    item_cache_2 = ItemCache(config)
+    assert item_cache_2["/d/c"]["v"] == "c"
     with open(os.path.join(tmpdir, "spec", "d", "c.yml"), "w+") as out:
         out.write("links:\n- role: null\n  uid: ../p\nv: x\n")
-    ic3 = ItemCache(config)
-    assert ic3["/d/c"]["v"] == "x"
+    item_cache_3 = ItemCache(config)
+    assert item_cache_3["/d/c"]["v"] == "x"
+
+
+class Mapper(ItemMapper):
+    def __init__(self, item):
+        super().__init__(item)
+
+    def u(self, value):
+        return "u" + value
+
+    def v(self, value):
+        return "v" + value
+
+    def dup(self, value):
+        return value + value
+
+    def x_to_b(self, item, value):
+        return value["b"]
+
+
+def test_item_mapper(tmpdir):
+    config = _create_spec_and_config(tmpdir)
+    item_cache = ItemCache(config)
+    item = item_cache["/p"]
+    mapper = Mapper(item)
+    with mapper.prefix("v"):
+        assert mapper[".:."] == "p"
+        assert mapper[".:../x/y"] == "z"
+        item_2, value_2 = mapper.map(".:.")
+        assert item == item_2
+        assert value_2 == "p"
+        assert mapper.substitute("$$${.:.}") == "$p"
+    with mapper.prefix("x"):
+        with mapper.prefix("y"):
+            assert mapper[".:."] == "z"
+    assert mapper["d/c:v"] == "c"
+    assert mapper["d/c:a/b"] == "e"
+    assert mapper["d/c:a/b|u"] == "ue"
+    assert mapper["d/c:a/x-to-b|u|v"] == "vue"
+    assert mapper["d/c:a/f[1]"] == 2
+    assert mapper["d/c:a/../a/f[3]/g[0]|dup"] == 8
+    item_3, value_3 = mapper.map("/p:/v")
+    assert item == item_3
+    assert value_3 == "p"
+    with pytest.raises(StopIteration):
+        for something in mapper:
+            pass
+    with pytest.raises(AttributeError):
+        len(mapper)
