← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~fcavalieri/zorba/identifiers into lp:zorba

 

Federico Cavalieri has proposed merging lp:~fcavalieri/zorba/identifiers into lp:zorba.

Requested reviews:
  Markos Zaharioudakis (markos-za)

For more details, see:
https://code.launchpad.net/~fcavalieri/zorba/identifiers/+merge/77297

Introduced a core module which allows to compute a unique identifier which can be used to retrieve a node (even temporary) during all its lifetime. 
Added three functions to the store api for computing identifier, assessing if a node already has an identifier and retrieving a node given its identifier. 
The simplestore extension comprises additional methods for working with identifiers in a PUL manipulation context.
-- 
https://code.launchpad.net/~fcavalieri/zorba/identifiers/+merge/77297
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
--- include/zorba/pregenerated/diagnostic_list.h	2011-08-17 23:04:48 +0000
+++ include/zorba/pregenerated/diagnostic_list.h	2011-09-28 09:26:25 +0000
@@ -500,6 +500,12 @@
 
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZAPI0080_CANNOT_RETRIEVE_NODE_REFERENCE;
 
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZAPI0090_NO_CURRENT_IDENTIFIER;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZAPI0091_INVALID_NODE_IDENTIFIER;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZAPI0092_IDENTIFIER_ALREADY_PRESENT;
+
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZCSE0001_NONEXISTENT_INPUT_FIELD;
 
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZCSE0002_INCOMPATIBLE_INPUT_FIELD;

=== modified file 'modules/com/zorba-xquery/www/modules/CMakeLists.txt'
--- modules/com/zorba-xquery/www/modules/CMakeLists.txt	2011-08-10 09:40:29 +0000
+++ modules/com/zorba-xquery/www/modules/CMakeLists.txt	2011-09-28 09:26:25 +0000
@@ -46,6 +46,8 @@
   URI "http://www.zorba-xquery.com/modules/math";)
 DECLARE_ZORBA_MODULE(FILE node-reference.xq VERSION 2.0
   URI "http://www.zorba-xquery.com/modules/node-reference";)
+DECLARE_ZORBA_MODULE(FILE node-identifier.xq VERSION 2.0
+  URI "http://www.zorba-xquery.com/modules/node-identifier";)
 DECLARE_ZORBA_MODULE(FILE node.xq VERSION 2.0
   URI "http://www.zorba-xquery.com/modules/node";)
 DECLARE_ZORBA_MODULE(FILE project_xqdoc.xq VERSION 2.0

=== added file 'modules/com/zorba-xquery/www/modules/node-identifier.xq'
--- modules/com/zorba-xquery/www/modules/node-identifier.xq	1970-01-01 00:00:00 +0000
+++ modules/com/zorba-xquery/www/modules/node-identifier.xq	2011-09-28 09:26:25 +0000
@@ -0,0 +1,106 @@
+xquery version "3.0";
+
+(:
+ : Copyright 2006-2011 The FLWOR Foundation.
+ :
+ : Licensed under the Apache License, Version 2.0 (the "License");
+ : you may not use this file except in compliance with the License.
+ : You may obtain a copy of the License at
+ :
+ : http://www.apache.org/licenses/LICENSE-2.0
+ :
+ : Unless required by applicable law or agreed to in writing, software
+ : distributed under the License is distributed on an "AS IS" BASIS,
+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ : See the License for the specific language governing permissions and
+ : limitations under the License.
+:)
+
+(:~
+ : This module provides functions to compute a string identifier for
+ : any node, either temporary or stored in a collection and for retrieving
+ : nodes given their identifier. The identifiers are immutable, i.e. a node 
+ : identifier do not change during the node lifetime. Identifiers are also 
+ : unique in that an already generated identifier cannot be generated again.
+ : Morever a node, at any time during its lifetime can be retrieved by its 
+ : identifier.
+ :
+ : @author Federico Cavalieri 
+ :)
+module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+declare namespace ann = "http://www.zorba-xquery.com/annotations";;
+declare namespace ver = "http://www.zorba-xquery.com/options/versioning";;
+declare option ver:module-version "2.0";
+
+(:~
+ : Computes a UUID string identifier (with type xs:string) for the given node.
+ : If an identifier has been already generated for the the given node it is 
+ : returned. Otherwise a new identifier is generated and returned.
+ :
+ : <p>The returned identifier is immutable, i.e., a node identifier
+ : do not change during the node lifetime.</p>
+ :
+ : <p>The returned identifier is unique, i.e. the same identifier cannot be
+ : generated again.</p>
+ :
+ : @param $arg the node for which the identifier should be computed 
+ :
+ : @return the identifier of the node
+ :
+ :)
+declare function id:node-identifier(
+  $node as node()
+) as xs:string external;
+
+(:~
+ : Computes a UUID string identifier (with type xs:string) for the given node.
+ : If an identifier has been already generated for the the given node it is 
+ : returned.
+ :
+ : <p>The returned identifier is stable, i.e. the corresoponding node
+ : can be retrieved at any time during its lifetime.</p>
+ :
+ : <p>The returned identifier is unique, i.e. the same identifier cannot be
+ : generated again.</p>
+ :
+ : @param $arg the node for which the identifier should be computed 
+ :
+ : @return the identifier of the node
+ :
+ : @error zerr::ZAPI0091 if no identifier has been generated for the given node
+ : computed by the <pre>id:node-identifier</pre> function
+ :
+ :)
+declare function id:current-node-identifier(
+  $node as node()
+) as xs:string external;
+ 
+(:~
+ : Returns whether an identifier has already been generated the given node or not.
+ :  
+ : @param $node a node 
+ :
+ : @return whether an identifier has already been generated the given node or not
+ :)
+declare function id:has-identifier(
+  $node as node()  
+) as xs:boolean external;
+
+(:~
+ : Returns the node which is identified by the given identifier.
+ :
+ : <p>The function return the empty sequence if the corresponding 
+ : node has been deleted or if the given identifier has never been
+ : generated.</p>  
+ :
+ : @param $node-identifier the identifier of the node to retrieve
+ :
+ : @return the node identified by the given identifier or empty-sequence
+ : if it cannot be retrieved
+ :
+ : @error zerr::ZAPI0091 if the given identifier is not a valid identifier
+ : computed by the <pre>id:node-identifier</pre> function
+ :)
+declare function id:node-by-identifier(
+  $arg as xs:string
+) as node()? external;

=== modified file 'modules/com/zorba-xquery/www/modules/pregenerated/errors.xq'
--- modules/com/zorba-xquery/www/modules/pregenerated/errors.xq	2011-08-17 23:04:48 +0000
+++ modules/com/zorba-xquery/www/modules/pregenerated/errors.xq	2011-09-28 09:26:25 +0000
@@ -301,6 +301,18 @@
 
 (:~
 :)
+declare variable $zerr:ZAPI0090 as xs:QName := fn:QName($zerr:NS, "zerr:ZAPI0090");
+
+(:~
+:)
+declare variable $zerr:ZAPI0091 as xs:QName := fn:QName($zerr:NS, "zerr:ZAPI0091");
+
+(:~
+:)
+declare variable $zerr:ZAPI0092 as xs:QName := fn:QName($zerr:NS, "zerr:ZAPI0092");
+
+(:~
+:)
 declare variable $zerr:ZCSE0001 as xs:QName := fn:QName($zerr:NS, "zerr:ZCSE0001");
 
 (:~

=== modified file 'src/context/static_context.cpp'
--- src/context/static_context.cpp	2011-09-06 14:05:29 +0000
+++ src/context/static_context.cpp	2011-09-28 09:26:25 +0000
@@ -280,6 +280,9 @@
 static_context::ZORBA_NODEREF_FN_NS = NS_PRE + "modules/node-reference";
 
 const zstring
+static_context::ZORBA_NODEID_FN_NS= NS_PRE + "modules/node-identifier";
+
+const zstring
 static_context::ZORBA_STORE_DYNAMIC_COLLECTIONS_DDL_FN_NS
   = NS_PRE + "modules/store/dynamic/collections/ddl";
 
@@ -373,6 +376,7 @@
     return (ns == ZORBA_MATH_FN_NS ||
             ns == ZORBA_BASE64_FN_NS ||
             ns == ZORBA_NODEREF_FN_NS ||
+            ns == ZORBA_NODEID_FN_NS ||
             ns == ZORBA_STORE_DYNAMIC_DOCUMENTS_FN_NS ||
             ns == ZORBA_STORE_DYNAMIC_UNORDERED_MAP_FN_NS ||
             ns == ZORBA_STORE_DYNAMIC_COLLECTIONS_DDL_FN_NS ||

=== modified file 'src/context/static_context.h'
--- src/context/static_context.h	2011-08-31 13:17:59 +0000
+++ src/context/static_context.h	2011-09-28 09:26:25 +0000
@@ -459,6 +459,7 @@
   static const zstring ZORBA_MATH_FN_NS;
   static const zstring ZORBA_BASE64_FN_NS;
   static const zstring ZORBA_NODEREF_FN_NS;
+  static const zstring ZORBA_NODEID_FN_NS;
   static const zstring ZORBA_STORE_DYNAMIC_COLLECTIONS_DDL_FN_NS;
   static const zstring ZORBA_STORE_DYNAMIC_COLLECTIONS_DML_FN_NS;
   static const zstring ZORBA_STORE_STATIC_COLLECTIONS_DDL_FN_NS;

=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml	2011-09-16 21:58:20 +0000
+++ src/diagnostics/diagnostic_en.xml	2011-09-28 09:26:25 +0000
@@ -1792,6 +1792,18 @@
       <value>can not retrieve node-reference for a node that is not in a collection.</value>
     </diagnostic>
 
+    <diagnostic code="ZAPI0090" name="NO_CURRENT_IDENTIFIER">
+      <value>node has no current identifier.</value>
+    </diagnostic>
+    
+    <diagnostic code="ZAPI0091" name="INVALID_NODE_IDENTIFIER">
+      <value>"$1": invalid node identifier.</value>
+    </diagnostic>
+    
+    <diagnostic code="ZAPI0092" name="IDENTIFIER_ALREADY_PRESENT">
+      <value>"$1": identifier already present in the store.</value>
+    </diagnostic>
+    
     <!--////////// Zorba Class Serialization Errors ////////////////////////-->
 
     <diagnostic code="ZCSE0001" name="NONEXISTENT_INPUT_FIELD">

=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
--- src/diagnostics/pregenerated/diagnostic_list.cpp	2011-08-17 23:04:48 +0000
+++ src/diagnostics/pregenerated/diagnostic_list.cpp	2011-09-28 09:26:25 +0000
@@ -729,6 +729,15 @@
 ZorbaErrorCode ZAPI0080_CANNOT_RETRIEVE_NODE_REFERENCE( "ZAPI0080" );
 
 
+ZorbaErrorCode ZAPI0090_NO_CURRENT_IDENTIFIER( "ZAPI0090" );
+
+
+ZorbaErrorCode ZAPI0091_INVALID_NODE_IDENTIFIER( "ZAPI0091" );
+
+
+ZorbaErrorCode ZAPI0092_IDENTIFIER_ALREADY_PRESENT( "ZAPI0092" );
+
+
 ZorbaErrorCode ZCSE0001_NONEXISTENT_INPUT_FIELD( "ZCSE0001" );
 
 

=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp	2011-09-16 21:58:20 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp	2011-09-28 09:26:25 +0000
@@ -244,6 +244,9 @@
   { "ZAPI0042", "iterator is closed" },
   { "ZAPI0070", "\"$1\": invalid serialization method for SAX" },
   { "ZAPI0080", "can not retrieve node-reference for a node that is not in a collection." },
+  { "ZAPI0090", "node has no current identifier." },
+  { "ZAPI0091", "\"$1\": invalid node identifier." },
+  { "ZAPI0092", "\"$1\": identifier already present in the store." },
   { "ZCSE0001", "\"$1\": nonexistent input field" },
   { "ZCSE0002", "\"$1\": incompatible input field${: type=2}${, class=3}" },
   { "ZCSE0003", "\"$1\": unrecognized class field" },

=== modified file 'src/functions/pregenerated/func_nodes.cpp'
--- src/functions/pregenerated/func_nodes.cpp	2011-08-04 02:39:56 +0000
+++ src/functions/pregenerated/func_nodes.cpp	2011-09-28 09:26:25 +0000
@@ -31,6 +31,46 @@
 
 
 
+PlanIter_t zorba_node_identifier_node_identifier::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  AnnotationHolder& ann) const
+{
+  return new NodeIdentifierIterator(sctx, loc, argv);
+}
+
+PlanIter_t zorba_node_identifier_current_node_identifier::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  AnnotationHolder& ann) const
+{
+  return new CurrentNodeIdentifierIterator(sctx, loc, argv);
+}
+
+PlanIter_t zorba_node_identifier_has_identifier::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  AnnotationHolder& ann) const
+{
+  return new HasIdentifierIterator(sctx, loc, argv);
+}
+
+PlanIter_t zorba_node_identifier_node_by_identifier::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  AnnotationHolder& ann) const
+{
+  return new NodeByIdentifierIterator(sctx, loc, argv);
+}
+
 PlanIter_t fn_zorba_ref_node_reference::codegen(
   CompilerCB*,
   static_context* sctx,
@@ -236,6 +276,54 @@
   {
     
 
+    DECL_WITH_KIND(sctx, zorba_node_identifier_node_identifier,
+        (createQName("http://www.zorba-xquery.com/modules/node-identifier","","node-identifier";), 
+        GENV_TYPESYSTEM.ANY_NODE_TYPE_ONE, 
+        GENV_TYPESYSTEM.STRING_TYPE_ONE),
+        FunctionConsts::ZORBA_NODE_IDENTIFIER_NODE_IDENTIFIER_1);
+
+  }
+
+
+  {
+    
+
+    DECL_WITH_KIND(sctx, zorba_node_identifier_current_node_identifier,
+        (createQName("http://www.zorba-xquery.com/modules/node-identifier","","current-node-identifier";), 
+        GENV_TYPESYSTEM.ANY_NODE_TYPE_ONE, 
+        GENV_TYPESYSTEM.STRING_TYPE_ONE),
+        FunctionConsts::ZORBA_NODE_IDENTIFIER_CURRENT_NODE_IDENTIFIER_1);
+
+  }
+
+
+  {
+    
+
+    DECL_WITH_KIND(sctx, zorba_node_identifier_has_identifier,
+        (createQName("http://www.zorba-xquery.com/modules/node-identifier","","has-identifier";), 
+        GENV_TYPESYSTEM.ANY_NODE_TYPE_ONE, 
+        GENV_TYPESYSTEM.BOOLEAN_TYPE_ONE),
+        FunctionConsts::ZORBA_NODE_IDENTIFIER_HAS_IDENTIFIER_1);
+
+  }
+
+
+  {
+    
+
+    DECL_WITH_KIND(sctx, zorba_node_identifier_node_by_identifier,
+        (createQName("http://www.zorba-xquery.com/modules/node-identifier","","node-by-identifier";), 
+        GENV_TYPESYSTEM.STRING_TYPE_ONE, 
+        GENV_TYPESYSTEM.ANY_NODE_TYPE_QUESTION),
+        FunctionConsts::ZORBA_NODE_IDENTIFIER_NODE_BY_IDENTIFIER_1);
+
+  }
+
+
+  {
+    
+
     DECL_WITH_KIND(sctx, fn_zorba_ref_node_reference,
         (createQName("http://www.zorba-xquery.com/modules/node-reference","","node-reference";), 
         GENV_TYPESYSTEM.ANY_NODE_TYPE_ONE, 

=== modified file 'src/functions/pregenerated/func_nodes.h'
--- src/functions/pregenerated/func_nodes.h	2011-06-16 19:47:58 +0000
+++ src/functions/pregenerated/func_nodes.h	2011-09-28 09:26:25 +0000
@@ -38,6 +38,58 @@
 
 
 
+//zorba-node-identifier:node-identifier
+class zorba_node_identifier_node_identifier : public function
+{
+public:
+  zorba_node_identifier_node_identifier(const signature& sig, FunctionConsts::FunctionKind kind)
+    : function(sig, kind) {
+
+}
+
+  CODEGEN_DECL();
+};
+
+
+//zorba-node-identifier:current-node-identifier
+class zorba_node_identifier_current_node_identifier : public function
+{
+public:
+  zorba_node_identifier_current_node_identifier(const signature& sig, FunctionConsts::FunctionKind kind)
+    : function(sig, kind) {
+
+}
+
+  CODEGEN_DECL();
+};
+
+
+//zorba-node-identifier:has-identifier
+class zorba_node_identifier_has_identifier : public function
+{
+public:
+  zorba_node_identifier_has_identifier(const signature& sig, FunctionConsts::FunctionKind kind)
+    : function(sig, kind) {
+
+}
+
+  CODEGEN_DECL();
+};
+
+
+//zorba-node-identifier:node-by-identifier
+class zorba_node_identifier_node_by_identifier : public function
+{
+public:
+  zorba_node_identifier_node_by_identifier(const signature& sig, FunctionConsts::FunctionKind kind)
+    : function(sig, kind) {
+
+}
+
+  CODEGEN_DECL();
+};
+
+
 //fn-zorba-ref:node-reference
 class fn_zorba_ref_node_reference : public function
 {

=== modified file 'src/functions/pregenerated/function_enum.h'
--- src/functions/pregenerated/function_enum.h	2011-08-17 20:22:07 +0000
+++ src/functions/pregenerated/function_enum.h	2011-09-28 09:26:25 +0000
@@ -193,6 +193,10 @@
   FN_ZORBA_MATH_IS_NAN_1,
   FN_ZORBA_MATH_MODF_1,
   FN_ZORBA_MATH_FREXP_1,
+  ZORBA_NODE_IDENTIFIER_NODE_IDENTIFIER_1,
+  ZORBA_NODE_IDENTIFIER_CURRENT_NODE_IDENTIFIER_1,
+  ZORBA_NODE_IDENTIFIER_HAS_IDENTIFIER_1,
+  ZORBA_NODE_IDENTIFIER_NODE_BY_IDENTIFIER_1,
   FN_ZORBA_REF_NODE_REFERENCE_1,
   FN_ZORBA_REF_NODE_BY_REFERENCE_1,
   FN_LOCAL_NAME_0,

=== modified file 'src/runtime/nodes/nodes_impl.cpp'
--- src/runtime/nodes/nodes_impl.cpp	2011-08-04 02:39:56 +0000
+++ src/runtime/nodes/nodes_impl.cpp	2011-09-28 09:26:25 +0000
@@ -33,6 +33,97 @@
 
 namespace zorba {
 
+/*******************************************************************************
+********************************************************************************/
+bool
+NodeIdentifierIterator::nextImpl(store::Item_t& aResult, PlanState& aPlanState) const
+{
+  store::Item_t lNode;
+  store::Item_t lGenerateIdentifier;
+  zstring lNodeId;
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState);
+
+  consumeNext(lNode, theChildren[0].getp(), aPlanState);
+
+  STACK_PUSH(GENV_STORE.getIdentifier(aResult, lNode), state);
+
+  STACK_END (state);
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool
+CurrentNodeIdentifierIterator::nextImpl(store::Item_t& aResult, PlanState& aPlanState) const
+{
+  store::Item_t lNode;
+  store::Item_t lGenerateIdentifier;
+  zstring lNodeId;
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState);
+
+  consumeNext(lNode, theChildren[0].getp(), aPlanState);
+
+  if (!GENV_STORE.hasIdentifier(lNode))
+  {
+    throw XQUERY_EXCEPTION(
+      zerr::ZAPI0090_NO_CURRENT_IDENTIFIER,
+      ERROR_LOC( loc )
+    );
+  }
+  STACK_PUSH(GENV_STORE.getIdentifier(aResult, lNode), state);
+
+  STACK_END (state);
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool
+HasIdentifierIterator::nextImpl(store::Item_t& aResult, PlanState& aPlanState) const
+{
+  store::Item_t lNode;
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState);
+
+  consumeNext(lNode, theChildren[0].getp(), aPlanState);
+
+  STACK_PUSH(GENV_ITEMFACTORY->createBoolean(aResult, GENV_STORE.hasIdentifier(lNode)), state);
+
+  STACK_END (state);
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool
+NodeByIdentifierIterator::nextImpl(store::Item_t& result, PlanState& planState) const
+{
+    store::Item_t lUUID;
+
+    PlanIteratorState *state;
+    DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
+
+    consumeNext(lUUID, theChildren[0].getp(), planState);
+
+    if (!utf8::match_whole(lUUID->getStringValue(), "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"))
+    {
+      throw XQUERY_EXCEPTION(
+        zerr::ZAPI0091_INVALID_NODE_IDENTIFIER,
+        ERROR_PARAMS(lUUID->getStringValue()),
+        ERROR_LOC( loc )
+      );
+    }
+
+
+    STACK_PUSH(GENV_STORE.getNodeByIdentifier(result, lUUID->getStringValue()), state);
+
+    STACK_END (state);
+}
+
+
+
 bool NodeReferenceIterator::nextImpl(store::Item_t& result, PlanState& planState) const
 {
   PlanIteratorState *state;

=== modified file 'src/runtime/nodes/pregenerated/nodes.cpp'
--- src/runtime/nodes/pregenerated/nodes.cpp	2011-06-16 19:47:58 +0000
+++ src/runtime/nodes/pregenerated/nodes.cpp	2011-09-28 09:26:25 +0000
@@ -32,6 +32,118 @@
 
 namespace zorba {
 
+// <NodeIdentifierIterator>
+const char* NodeIdentifierIterator::class_name_str = "NodeIdentifierIterator";
+NodeIdentifierIterator::class_factory<NodeIdentifierIterator>
+NodeIdentifierIterator::g_class_factory;
+
+const serialization::ClassVersion 
+NodeIdentifierIterator::class_versions[] ={{ 1, 0x000905, false}};
+
+const int NodeIdentifierIterator::class_versions_count =
+sizeof(NodeIdentifierIterator::class_versions)/sizeof(struct serialization::ClassVersion);
+
+void NodeIdentifierIterator::accept(PlanIterVisitor& v) const {
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+NodeIdentifierIterator::~NodeIdentifierIterator() {}
+
+// </NodeIdentifierIterator>
+
+
+// <CurrentNodeIdentifierIterator>
+const char* CurrentNodeIdentifierIterator::class_name_str = "CurrentNodeIdentifierIterator";
+CurrentNodeIdentifierIterator::class_factory<CurrentNodeIdentifierIterator>
+CurrentNodeIdentifierIterator::g_class_factory;
+
+const serialization::ClassVersion 
+CurrentNodeIdentifierIterator::class_versions[] ={{ 1, 0x000905, false}};
+
+const int CurrentNodeIdentifierIterator::class_versions_count =
+sizeof(CurrentNodeIdentifierIterator::class_versions)/sizeof(struct serialization::ClassVersion);
+
+void CurrentNodeIdentifierIterator::accept(PlanIterVisitor& v) const {
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+CurrentNodeIdentifierIterator::~CurrentNodeIdentifierIterator() {}
+
+// </CurrentNodeIdentifierIterator>
+
+
+// <HasIdentifierIterator>
+const char* HasIdentifierIterator::class_name_str = "HasIdentifierIterator";
+HasIdentifierIterator::class_factory<HasIdentifierIterator>
+HasIdentifierIterator::g_class_factory;
+
+const serialization::ClassVersion 
+HasIdentifierIterator::class_versions[] ={{ 1, 0x000905, false}};
+
+const int HasIdentifierIterator::class_versions_count =
+sizeof(HasIdentifierIterator::class_versions)/sizeof(struct serialization::ClassVersion);
+
+void HasIdentifierIterator::accept(PlanIterVisitor& v) const {
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+HasIdentifierIterator::~HasIdentifierIterator() {}
+
+// </HasIdentifierIterator>
+
+
+// <NodeByIdentifierIterator>
+const char* NodeByIdentifierIterator::class_name_str = "NodeByIdentifierIterator";
+NodeByIdentifierIterator::class_factory<NodeByIdentifierIterator>
+NodeByIdentifierIterator::g_class_factory;
+
+const serialization::ClassVersion 
+NodeByIdentifierIterator::class_versions[] ={{ 1, 0x000905, false}};
+
+const int NodeByIdentifierIterator::class_versions_count =
+sizeof(NodeByIdentifierIterator::class_versions)/sizeof(struct serialization::ClassVersion);
+
+void NodeByIdentifierIterator::accept(PlanIterVisitor& v) const {
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+NodeByIdentifierIterator::~NodeByIdentifierIterator() {}
+
+// </NodeByIdentifierIterator>
+
+
 // <NodeReferenceIterator>
 const char* NodeReferenceIterator::class_name_str = "NodeReferenceIterator";
 NodeReferenceIterator::class_factory<NodeReferenceIterator>

=== modified file 'src/runtime/nodes/pregenerated/nodes.h'
--- src/runtime/nodes/pregenerated/nodes.h	2011-06-16 19:47:58 +0000
+++ src/runtime/nodes/pregenerated/nodes.h	2011-09-28 09:26:25 +0000
@@ -34,6 +34,150 @@
 namespace zorba {
 
 /**
+ *        
+ *      declare function id:node-identifier($node as node) as xs:string
+ *    
+ * Author: Federico Cavalieri
+ */
+class NodeIdentifierIterator : public NaryBaseIterator<NodeIdentifierIterator, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(NodeIdentifierIterator);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(NodeIdentifierIterator,
+    NaryBaseIterator<NodeIdentifierIterator, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar)
+  {
+    serialize_baseclass(ar,
+    (NaryBaseIterator<NodeIdentifierIterator, PlanIteratorState>*)this);
+  }
+
+  NodeIdentifierIterator(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<NodeIdentifierIterator, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~NodeIdentifierIterator();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ *        
+ *      declare function id:current-node-identifier($node as node) as xs:string
+ *    
+ * Author: Federico Cavalieri
+ */
+class CurrentNodeIdentifierIterator : public NaryBaseIterator<CurrentNodeIdentifierIterator, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(CurrentNodeIdentifierIterator);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(CurrentNodeIdentifierIterator,
+    NaryBaseIterator<CurrentNodeIdentifierIterator, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar)
+  {
+    serialize_baseclass(ar,
+    (NaryBaseIterator<CurrentNodeIdentifierIterator, PlanIteratorState>*)this);
+  }
+
+  CurrentNodeIdentifierIterator(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<CurrentNodeIdentifierIterator, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~CurrentNodeIdentifierIterator();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ * 
+ *      declare function ref:has-identifier($node as node) as xs:boolean
+ *    
+ * Author: Federico Cavalieri
+ */
+class HasIdentifierIterator : public NaryBaseIterator<HasIdentifierIterator, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(HasIdentifierIterator);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(HasIdentifierIterator,
+    NaryBaseIterator<HasIdentifierIterator, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar)
+  {
+    serialize_baseclass(ar,
+    (NaryBaseIterator<HasIdentifierIterator, PlanIteratorState>*)this);
+  }
+
+  HasIdentifierIterator(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<HasIdentifierIterator, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~HasIdentifierIterator();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ * 
+ *      declare function ref:node-by-identifier($identifier as xs:string) as node()?
+ *    
+ * Author: Federico Cavalieri
+ */
+class NodeByIdentifierIterator : public NaryBaseIterator<NodeByIdentifierIterator, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(NodeByIdentifierIterator);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(NodeByIdentifierIterator,
+    NaryBaseIterator<NodeByIdentifierIterator, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar)
+  {
+    serialize_baseclass(ar,
+    (NaryBaseIterator<NodeByIdentifierIterator, PlanIteratorState>*)this);
+  }
+
+  NodeByIdentifierIterator(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<NodeByIdentifierIterator, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~NodeByIdentifierIterator();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
  * 
  *  Iterator to implement the zorba:node-reference function.
  *  

=== modified file 'src/runtime/spec/mappings.xml'
--- src/runtime/spec/mappings.xml	2011-07-26 21:03:39 +0000
+++ src/runtime/spec/mappings.xml	2011-09-28 09:26:25 +0000
@@ -24,6 +24,10 @@
                      define="ZORBA_NODEREF_FN_NS"
                      prefix="fn-zorba-ref"/> 
 
+    <zorba:namespace uri="http://www.zorba-xquery.com/modules/node-identifier";
+      define="ZORBA_NODEID_FN_NS"
+      prefix="zorba-node-identifier"/>
+
     <zorba:namespace uri="http://www.zorba-xquery.com/modules/schema";
                      define="ZORBA_SCHEMA_FN_NS"
                      prefix="fn-zorba-schema"/>

=== modified file 'src/runtime/spec/nodes/nodes.xml'
--- src/runtime/spec/nodes/nodes.xml	2011-08-04 02:39:56 +0000
+++ src/runtime/spec/nodes/nodes.xml	2011-09-28 09:26:25 +0000
@@ -11,6 +11,90 @@
   xmlns:zorba="http://www.zorba-xquery.com";
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xsi:schemaLocation="http://www.zorba-xquery.com ../runtime.xsd">
+
+<!--
+/*******************************************************************************
+********************************************************************************/
+-->
+  <zorba:iterator name="NodeIdentifierIterator">
+
+    <zorba:description author="Federico Cavalieri">       
+      declare function id:node-identifier($node as node) as xs:string
+    </zorba:description>
+    
+    <zorba:function>
+    
+      <zorba:signature localname="node-identifier" prefix="zorba-node-identifier">
+        <zorba:param>node()</zorba:param>   
+        <zorba:output>xs:string</zorba:output>
+      </zorba:signature>
+      
+    </zorba:function>
+
+  </zorba:iterator>
+  
+<!--
+/*******************************************************************************
+********************************************************************************/
+-->
+  <zorba:iterator name="CurrentNodeIdentifierIterator">
+
+    <zorba:description author="Federico Cavalieri">       
+      declare function id:current-node-identifier($node as node) as xs:string
+    </zorba:description>
+    
+    <zorba:function>
+    
+      <zorba:signature localname="current-node-identifier" prefix="zorba-node-identifier">
+        <zorba:param>node()</zorba:param>   
+        <zorba:output>xs:string</zorba:output>
+      </zorba:signature>
+      
+    </zorba:function>
+
+  </zorba:iterator>
+
+<!--
+/*******************************************************************************
+********************************************************************************/
+-->
+  <zorba:iterator name="HasIdentifierIterator">
+
+    <zorba:description author="Federico Cavalieri">
+      declare function ref:has-identifier($node as node) as xs:boolean
+    </zorba:description>
+    
+    <zorba:function>
+    
+      <zorba:signature localname="has-identifier" prefix="zorba-node-identifier">
+        <zorba:param>node()</zorba:param>                
+        <zorba:output>xs:boolean</zorba:output>
+      </zorba:signature>
+      
+    </zorba:function>
+
+  </zorba:iterator>
+
+<!--
+/*******************************************************************************
+********************************************************************************/
+-->
+  <zorba:iterator name="NodeByIdentifierIterator">
+
+    <zorba:description author="Federico Cavalieri">
+      declare function ref:node-by-identifier($identifier as xs:string) as node()?
+    </zorba:description>
+
+    <zorba:function>
+    
+      <zorba:signature localname="node-by-identifier" prefix="zorba-node-identifier">        
+        <zorba:param>xs:string</zorba:param>        
+        <zorba:output>node()?</zorba:output>
+      </zorba:signature>
+      
+    </zorba:function>
+        
+  </zorba:iterator>
     
 <!--
 /*******************************************************************************

=== modified file 'src/runtime/visitors/pregenerated/planiter_visitor.h'
--- src/runtime/visitors/pregenerated/planiter_visitor.h	2011-08-17 20:22:07 +0000
+++ src/runtime/visitors/pregenerated/planiter_visitor.h	2011-09-28 09:26:25 +0000
@@ -303,6 +303,14 @@
 
     class FrexpIterator;
 
+    class NodeIdentifierIterator;
+
+    class CurrentNodeIdentifierIterator;
+
+    class HasIdentifierIterator;
+
+    class NodeByIdentifierIterator;
+
     class NodeReferenceIterator;
 
     class NodeByReferenceIterator;
@@ -955,6 +963,18 @@
     virtual void beginVisit ( const FrexpIterator& ) = 0;
     virtual void endVisit   ( const FrexpIterator& ) = 0;
 
+    virtual void beginVisit ( const NodeIdentifierIterator& ) = 0;
+    virtual void endVisit   ( const NodeIdentifierIterator& ) = 0;
+
+    virtual void beginVisit ( const CurrentNodeIdentifierIterator& ) = 0;
+    virtual void endVisit   ( const CurrentNodeIdentifierIterator& ) = 0;
+
+    virtual void beginVisit ( const HasIdentifierIterator& ) = 0;
+    virtual void endVisit   ( const HasIdentifierIterator& ) = 0;
+
+    virtual void beginVisit ( const NodeByIdentifierIterator& ) = 0;
+    virtual void endVisit   ( const NodeByIdentifierIterator& ) = 0;
+
     virtual void beginVisit ( const NodeReferenceIterator& ) = 0;
     virtual void endVisit   ( const NodeReferenceIterator& ) = 0;
 

=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.cpp'
--- src/runtime/visitors/pregenerated/printer_visitor.cpp	2011-08-17 20:22:07 +0000
+++ src/runtime/visitors/pregenerated/printer_visitor.cpp	2011-09-28 09:26:25 +0000
@@ -2013,6 +2013,62 @@
 // </FrexpIterator>
 
 
+// <NodeIdentifierIterator>
+void PrinterVisitor::beginVisit ( const NodeIdentifierIterator& a) {
+  thePrinter.startBeginVisit("NodeIdentifierIterator", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const NodeIdentifierIterator& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </NodeIdentifierIterator>
+
+
+// <CurrentNodeIdentifierIterator>
+void PrinterVisitor::beginVisit ( const CurrentNodeIdentifierIterator& a) {
+  thePrinter.startBeginVisit("CurrentNodeIdentifierIterator", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const CurrentNodeIdentifierIterator& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </CurrentNodeIdentifierIterator>
+
+
+// <HasIdentifierIterator>
+void PrinterVisitor::beginVisit ( const HasIdentifierIterator& a) {
+  thePrinter.startBeginVisit("HasIdentifierIterator", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const HasIdentifierIterator& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </HasIdentifierIterator>
+
+
+// <NodeByIdentifierIterator>
+void PrinterVisitor::beginVisit ( const NodeByIdentifierIterator& a) {
+  thePrinter.startBeginVisit("NodeByIdentifierIterator", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const NodeByIdentifierIterator& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </NodeByIdentifierIterator>
+
+
 // <NodeReferenceIterator>
 void PrinterVisitor::beginVisit ( const NodeReferenceIterator& a) {
   thePrinter.startBeginVisit("NodeReferenceIterator", ++theId);

=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.h'
--- src/runtime/visitors/pregenerated/printer_visitor.h	2011-08-17 20:22:07 +0000
+++ src/runtime/visitors/pregenerated/printer_visitor.h	2011-09-28 09:26:25 +0000
@@ -457,6 +457,18 @@
     void beginVisit( const FrexpIterator& );
     void endVisit  ( const FrexpIterator& );
 
+    void beginVisit( const NodeIdentifierIterator& );
+    void endVisit  ( const NodeIdentifierIterator& );
+
+    void beginVisit( const CurrentNodeIdentifierIterator& );
+    void endVisit  ( const CurrentNodeIdentifierIterator& );
+
+    void beginVisit( const HasIdentifierIterator& );
+    void endVisit  ( const HasIdentifierIterator& );
+
+    void beginVisit( const NodeByIdentifierIterator& );
+    void endVisit  ( const NodeByIdentifierIterator& );
+
     void beginVisit( const NodeReferenceIterator& );
     void endVisit  ( const NodeReferenceIterator& );
 

=== modified file 'src/store/api/copymode.h'
--- src/store/api/copymode.h	2011-06-14 17:26:33 +0000
+++ src/store/api/copymode.h	2011-09-28 09:26:25 +0000
@@ -34,13 +34,15 @@
   bool  theTypePreserve;
   bool  theNsPreserve;
   bool  theNsInherit;
+  bool	theFreezeIdentifier;
 
   CopyMode()
     :
     theDoCopy(true),
     theTypePreserve(true),
     theNsPreserve(true),
-    theNsInherit(true)
+    theNsInherit(true),
+    theFreezeIdentifier(false)
   {
   }
 
@@ -49,7 +51,8 @@
     theDoCopy(aCopyMode.theDoCopy),
     theTypePreserve(aCopyMode.theTypePreserve),
     theNsPreserve(aCopyMode.theNsPreserve),
-    theNsInherit(aCopyMode.theNsInherit)
+    theNsInherit(aCopyMode.theNsInherit),
+    theFreezeIdentifier(aCopyMode.theFreezeIdentifier)
   {
   }
 
@@ -57,12 +60,14 @@
         bool copy,
         bool typePreserve,
         bool nsPreserve,
-        bool nsInherit)
+        bool nsInherit,
+        bool freezeIdentifier=false)
   {
     theDoCopy = copy;
     theTypePreserve = typePreserve;
     theNsPreserve = nsPreserve;
     theNsInherit = nsInherit;
+    theFreezeIdentifier=freezeIdentifier;
   }
 
   std::string toString() const
@@ -76,6 +81,8 @@
     s += (theNsPreserve ? "T" : "F");
     s += " ";
     s += (theNsInherit ? "T" : "F");
+    s += " ";
+    s += (theFreezeIdentifier ? "T" : "F");
     s += "]";
     return s;
   }

=== modified file 'src/store/api/store.h'
--- src/store/api/store.h	2011-09-27 10:43:46 +0000
+++ src/store/api/store.h	2011-09-28 09:26:25 +0000
@@ -105,9 +105,38 @@
    * @returns referenced item if it exists, otherwise NULL
    */
   virtual bool getNodeByReference(Item_t& result, const Item* uri) = 0;
-		
-		
-  /* --------------------------- Node Id Management ---------------------------*/
+
+
+  /* ------------------------ Node Identifiers Management ---------------------------*/
+
+  /**
+   * Computes the identifier of the given node.
+   *
+   * @param result the identifier as an item of type xs:string
+   * @param node XDM node
+   * @return whether the identifier has been created successfully
+   */
+  virtual bool getIdentifier(Item_t& result, Item* node) = 0;
+
+  /**
+   * Returns whether an identifier has been generated for the given node.
+   *
+   * @param item XDM node
+   * @return whether an identifier has been generated for the given node.
+   */
+  virtual bool hasIdentifier(const Item* node) = 0;
+
+  /**
+   * Returns the node which is associated to the given identifier.
+   *
+   * @param result the node or NULL if not found
+   * @param identifier the identifier to dereference
+   * @returns whether the referenced item exists, NULL otherwise
+   */
+  virtual bool getNodeByIdentifier(store::Item_t& result, const zstring& identifier) = 0;
+
+
+  /* ------------------------ Node Identity Management ---------------------------*/
 
   /**
    * Compares two nodes, based on their node id.

=== modified file 'src/store/naive/node_items.cpp'
--- src/store/naive/node_items.cpp	2011-09-23 14:26:00 +0000
+++ src/store/naive/node_items.cpp	2011-09-28 09:26:25 +0000
@@ -693,6 +693,7 @@
   }
 #endif
 
+  GET_STORE().unregisterNode(this);
   delete this;
 }
 
@@ -1387,6 +1388,10 @@
     throw;
   }
 
+  if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+    GET_STORE().copyIdentifier(this,copyNode);
+
+
   NODE_TRACE1("}");
   NODE_TRACE1("Copied doc node " << this << " to node " << copyNode);
 
@@ -2011,6 +2016,9 @@
     throw;
   }
 
+  if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+    GET_STORE().copyIdentifier(this,copyNode);
+
   NODE_TRACE1("Copied elem node " << this << " to node " << copyNode
               << " name = " << theName->getStringValue() << " parent = "
               << (parent ? parent : 0x0)
@@ -3125,6 +3133,9 @@
     throw;
   }
 
+  if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+    GET_STORE().copyIdentifier(this,copyNode);
+
   NODE_TRACE1("Copied attribute node " << this << " to node " << copyNode
               << " name = " << theName->show() << " parent = "
               << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
@@ -3593,6 +3604,9 @@
     throw;
   }
 
+  if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+    GET_STORE().copyIdentifier(this,copyNode);
+
   NODE_TRACE1("Copied text node " << this << " to node " << copyNode
               << " parent = " << std::hex << (parent ? (ulong)parent : 0)
               << " pos = " << pos);
@@ -4079,6 +4093,9 @@
     throw;
   }
 
+  if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+    GET_STORE().copyIdentifier(this,copyNode);
+
   NODE_TRACE1("Copied pi node " << this << " to node " << copyNode
               << " parent = " << std::hex << (parent ? (ulong)parent : 0)
               << " pos = " << pos);
@@ -4202,6 +4219,9 @@
     throw;
   }
 
+  if (haveFrozenIdentifier() || copymode.theFreezeIdentifier)
+    GET_STORE().copyIdentifier(this,copyNode);
+
   NODE_TRACE1("Copied coment node " << this << " to node " << copyNode
               << " parent = " << std::hex << (parent ? (ulong)parent : 0)
               << " pos = " << pos);

=== modified file 'src/store/naive/node_items.h'
--- src/store/naive/node_items.h	2011-09-23 14:26:00 +0000
+++ src/store/naive/node_items.h	2011-09-28 09:26:25 +0000
@@ -325,14 +325,16 @@
 
     // For element nodes only. The flag is set for a node N if there is another
     // node M in its subtree such that N and M have the same name.
-    IsRecursive       =   0x4000
+    IsRecursive       =   0x4000,
 
 #ifndef EMBEDED_TYPE
-    ,
     // For element and attribute nodes only. The flag is set if the node has
     // a type other than untyped (for elements) or untypedAtomic (for attributes)
-    HaveType  =   0x8000
+    HaveType  =   0x8000,
 #endif
+
+    HaveIdentifier    = 0x10000,
+    HaveFrozenIdentifier = 0x20000
   };
 
 protected:
@@ -495,6 +497,15 @@
 
   void setFlags(uint32_t flags) { theFlags = flags; }
 
+  bool haveIdentifier() const         { return (theFlags & HaveIdentifier) != 0; }
+  void setHaveIdentifier()            { theFlags |= HaveIdentifier; }
+  void resetHaveIdentifier()          { theFlags &= ~HaveIdentifier; }
+
+  bool haveFrozenIdentifier() const   { return (theFlags & HaveFrozenIdentifier) != 0; }
+  void setHaveFrozenIdentifier()      { theFlags |= HaveFrozenIdentifier; }
+  void resetHaveFrozenIdentifier()    { theFlags &= ~HaveFrozenIdentifier; }
+
+
 #ifndef ZORBA_NO_FULL_TEXT
   FTTokenIterator_t getTokens( TokenizerProvider const&, Tokenizer::Numbers&,
                                locale::iso639_1::type, bool = false ) const;

=== modified file 'src/store/naive/simple_store.cpp'
--- src/store/naive/simple_store.cpp	2011-09-26 22:49:54 +0000
+++ src/store/naive/simple_store.cpp	2011-09-28 09:26:25 +0000
@@ -57,6 +57,7 @@
 #include "store/naive/pul_primitive_factory.h"
 
 #include "util/cxx_util.h"
+#include "util/uuid/uuid.h"
 
 #ifndef ZORBA_NO_FULL_TEXT
 #include "runtime/full_text/default_tokenizer.h"
@@ -334,6 +335,24 @@
       theNodeFactory = NULL;
     }
 
+    if(theNodeToIdentifiersMap.size()>0)
+    {
+      std::map<const store::Item *,zstring>::iterator iter= theNodeToIdentifiersMap.begin();
+      std::map<const store::Item *,zstring>::iterator end= theNodeToIdentifiersMap.end();
+      for (; iter != end; ++iter)
+        std::cerr << "Identifier: " << iter->first << "is still in the nodes to identifiers map" << std::endl;
+      ZORBA_FATAL(0, theNodeToIdentifiersMap.size()+" node identifiers still in the nodes to identifiers map");
+    }
+
+    if(theIdentifiersToNodeMap.size()>0)
+    {
+      std::map<const zstring,const store::Item *>::iterator iter= theIdentifiersToNodeMap.begin();
+      std::map<const zstring,const store::Item *>::iterator end= theIdentifiersToNodeMap.end();
+      for (; iter != end; ++iter)
+        std::cerr << "Identifier: " << iter->first << "is still in the identifiers to nodes map" << std::endl;
+      ZORBA_FATAL(0, theIdentifiersToNodeMap.size()+" node identifiers still in the identifiers to nodes map");
+    }
+
     // do cleanup of the libxml2 library
     // however, after that, a user will have to call
     // LIBXML_TEST_VERSION if he wants to use libxml2
@@ -1663,6 +1682,179 @@
   }
 }
 
+/* ------------------------ Node Identifiers Management ---------------------------*/
+
+/**
+ * Computes the identifier of the given node.
+ *
+ * @param result identifier as an item of type xs:string
+ * @param node XDM node
+ * @return whether the identifier has been created successfully
+ */
+bool SimpleStore::getIdentifier(store::Item_t& result, store::Item* node)
+{
+  std::map<const store::Item *,zstring>::iterator resIt;
+  if ((resIt=theNodeToIdentifiersMap.find(node))!=theNodeToIdentifiersMap.end())
+  {
+    //The node has already an associated identifier
+    zstring id=resIt->second;
+    return theItemFactory->createString(result, id);
+  }
+
+  uuid_t uuid;
+  uuid_create(&uuid);
+  zstring uuidStr=uuidToString(uuid);
+  zstring uuidStr2=uuidStr;
+  zstring uuidStr3=uuidStr;
+  static_cast<const XmlNode*>(node)->setHaveIdentifier();
+  theNodeToIdentifiersMap[node]=uuidStr;
+  theIdentifiersToNodeMap[uuidStr2]=node;
+  return theItemFactory->createString(result, uuidStr3);
+}
+
+/**
+ * Returns the already computed identifier of the given node.
+ * If no identifier has already been computed for the given node
+ * error ZAPI0090 is raised.
+ *
+ * @param result identifier as an item of type xs:string
+ * @param node XDM node
+ * @return whether the identifier has been created successfully
+ */
+bool SimpleStore::getCurrentIdentifier(store::Item_t& result, const store::Item* node)
+{
+  std::map<const store::Item *,zstring>::iterator resIt;
+  if ((resIt=theNodeToIdentifiersMap.find(node))!=theNodeToIdentifiersMap.end())
+  {
+    //The node has already an associated identifier
+    zstring id=resIt->second;
+    return theItemFactory->createString(result, id);
+  }
+  //The node has no identifier
+  throw ZORBA_EXCEPTION(zerr::ZAPI0090_NO_CURRENT_IDENTIFIER);
+}
+
+/**
+ * Returns the node which is associated to the given identifier.
+ *
+ * @param result the node or NULL if not found
+ * @param identifier the identifier to dereference
+ * @returns whether the referenced item exists, NULL otherwise
+ */
+bool SimpleStore::getNodeByIdentifier(store::Item_t& result, const zstring& identifier)
+{
+  std::map<const zstring, const store::Item *>::iterator resIt;
+  if ((resIt=theIdentifiersToNodeMap.find(identifier))!=theIdentifiersToNodeMap.end())
+  {
+    result=resIt->second;
+    return true;
+  }
+  result=NULL;
+  return false;
+}
+
+/**
+ * Returns whether an identifier has been generated for the given node.
+ *
+ * @param item XDM node
+ * @return whether an identifier has been generated for the given node.
+ */
+bool SimpleStore::hasIdentifier(const store::Item* node)
+{
+  return theNodeToIdentifiersMap.find(node)!=theNodeToIdentifiersMap.end();
+}
+
+/**
+ * Copies the identifier of a source node to a target node. The source
+ * node must already have an identifier. The target nodes acquires the
+ * source identifier but it is not registered in the identifier-to-node
+ * map. The target node also get its "haveFrozenIdentifier" flag set.
+ * Used in PUL manipulation.
+ *
+ * @param source source XDM node
+ * @param target target XDM node
+ */
+void SimpleStore::copyIdentifier(const XmlNode* source, XmlNode* target)
+{
+  store::Item_t identifier;
+  getCurrentIdentifier(identifier,source);
+  unregisterNode(target);
+  target->setHaveIdentifier();
+  target->setHaveFrozenIdentifier();
+  theNodeToIdentifiersMap[target]=identifier->getStringValue();
+}
+
+/**
+ * Sets the identifier of a node to a given value. The "haveFrozenIdentifer"
+ * flag is also set.
+ * Used in PUL manipulation.
+ *
+ * @param node  XDM node
+ * @param identifier the identifier to set
+ */
+void SimpleStore::restoreIdentifier(XmlNode* node, const zstring& identifier)
+{
+  unregisterNode(node);
+  theNodeToIdentifiersMap[node]=identifier;
+  node->setHaveIdentifier();
+  node->setHaveFrozenIdentifier();
+}
+
+/**
+ * Unfreezes the identifier of a given node:
+ * - Registers the node in the identifiers to node map
+ * - Resets the node "haveFrozenIdentifier" flag
+ * The node must already have an identifier, otherwise
+ * error ZAPI0090 is raised.
+ * The node identifier must not be used for any other
+ * node in the identifier-to-node map, otherwise
+ * error ZAPI0092 is raised.
+ * Used in PUL manipulation.
+ *
+ * @param node XDM node
+ */
+void SimpleStore::unfreezeIdentifier(XmlNode* node)
+{
+  store::Item_t identifier;
+  getCurrentIdentifier(identifier,node);
+  store::Item_t result;
+  if (getNodeByIdentifier(result, identifier->getStringValue()))
+  {
+    throw XQUERY_EXCEPTION(
+            zerr::ZAPI0092_IDENTIFIER_ALREADY_PRESENT,
+            ERROR_PARAMS(identifier->getStringValue())
+          );
+  }
+  theIdentifiersToNodeMap[identifier->getStringValue()]=node;
+  node->resetHaveFrozenIdentifier();
+}
+
+/**
+ * Removes a node from the identifier-to-nodes and nodes-to-identifiers maps.
+ *
+ * @param node XDM node
+ * @return whether the node was registered or not.
+ */
+bool SimpleStore::unregisterNode(XmlNode* node)
+{
+  if (!node->haveIdentifier())
+    return false;
+  std::map<const store::Item *,zstring>::iterator resIt;
+  if ((resIt=theNodeToIdentifiersMap.find(node))!=theNodeToIdentifiersMap.end())
+  {
+    zstring value=resIt->second;
+    theNodeToIdentifiersMap.erase(resIt);
+    node->resetHaveIdentifier();
+    if (!node->haveFrozenIdentifier())
+      theIdentifiersToNodeMap.erase(value);
+    else
+      node->resetHaveFrozenIdentifier();
+    //if a node has a frozen identifier it is not registered in the identifiers to node map
+    return true;
+  }
+  else
+    return false;
+}
 
 /*******************************************************************************
 

=== modified file 'src/store/naive/simple_store.h'
--- src/store/naive/simple_store.h	2011-09-26 22:49:54 +0000
+++ src/store/naive/simple_store.h	2011-09-28 09:26:25 +0000
@@ -142,6 +142,13 @@
 
   long                          theTraceLevel;
 
+  /* ------------------------ Node Identifiers Management ---------------------------*/
+
+  std::map<const zstring, const store::Item *> theIdentifiersToNodeMap;
+  std::map<const store::Item *, zstring> theNodeToIdentifiersMap;
+
+  /* ------------------------ Node Identifiers Management ---------------------------*/
+
 #ifndef ZORBA_NO_FULL_TEXT
   internal::StemmerProvider const * theStemmerProvider;
   TokenizerProvider const     * theTokenizerProvider;
@@ -332,6 +339,27 @@
 
   bool getNodeByReference(store::Item_t& result, const store::Item* uri);
 
+  /* ------------------------ Node Identifiers Management ---------------------------*/
+
+  bool getIdentifier(store::Item_t& result, store::Item* node);
+
+  bool getCurrentIdentifier(store::Item_t& result, const store::Item* node);
+
+  bool hasIdentifier(const store::Item* node);
+
+  bool getNodeByIdentifier(store::Item_t& result, const zstring& identifier);
+
+  bool unregisterNode(XmlNode* node);
+
+  void copyIdentifier(const XmlNode* source, XmlNode* target);
+
+  void restoreIdentifier(XmlNode* node, const zstring& identifier);
+
+  void unfreezeIdentifier(XmlNode* node);
+
+
+  /* ------------------------ Node Identifiers Management ---------------------------*/
+
   store::TempSeq_t createTempSeq(bool lazy);
 
   store::TempSeq_t createTempSeq(

=== added directory 'test/rbkt/ExpQueryResults/zorba/identifiers'
=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_1.xml.res	2011-09-28 09:26:25 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result><before hasid="false">36</before><after hasid="true">36</after><stable>true</stable></result>
\ No newline at end of file

=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_2.xml.res	2011-09-28 09:26:25 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result><out-of-module><root><child>text</child></root></out-of-module><temporary-variable/><in-scope><root><child>text</child></root></in-scope></result>
\ No newline at end of file

=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_3.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_3.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/identifiers_3.xml.res	2011-09-28 09:26:25 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result><before>No current id</before><get>36</get><after equal="true">36</after></result>
\ No newline at end of file

=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_1.xml.res	2011-09-28 09:26:25 +0000
@@ -0,0 +1,1 @@
+<doc>true true true true true true</doc><collection>true true true true true true</collection><in-memory>true true true true true true</in-memory>

=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_2.xml.res	2011-09-28 09:26:25 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<locked>true true true true true</locked><unlocked>false true false false true</unlocked>

=== added file 'test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_3.xml.res'
--- test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_3.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/identifiers/pul_identifiers_3.xml.res	2011-09-28 09:26:25 +0000
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result><test1><?processinginstruction someprocessinginstruction?><!-- This is a comment --><test2>
+	<?processinginstruction someprocessinginstruction1?>
+	<?processinginstruction someprocessinginstruction2?>
+	<?processinginstruction someprocessinginstruction3?>
+	<?processinginstruction someprocessinginstruction4?>
+	<!-- This is a comment1 -->
+	<!-- This is a comment2 -->
+	<!-- This is a comment3 -->
+	<nonEmptyElement1 emptyAttribute2="" emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement1>
+
+	<nonEmptyElement2 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement2>
+
+	<nonEmptyElement3 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement3>
+
+	<nonEmptyElement4 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement4>
+
+	<nonEmptyElement5 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement5>
+</test2></test1><test2><?processinginstruction someprocessinginstruction?><!-- This is a comment --><test2>
+	<?processinginstruction someprocessinginstruction1?>
+	<?processinginstruction someprocessinginstruction2?>
+	<?processinginstruction someprocessinginstruction3?>
+	<?processinginstruction someprocessinginstruction4?>
+	<!-- This is a comment1 -->
+	<!-- This is a comment2 -->
+	<!-- This is a comment3 -->
+	<nonEmptyElement1 emptyAttribute2="" emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement1>
+
+	<nonEmptyElement2 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement2>
+
+	<nonEmptyElement3 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement3>
+
+	<nonEmptyElement4 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement4>
+
+	<nonEmptyElement5 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement5>
+</test2></test2><test3><?processinginstruction someprocessinginstruction?><!-- This is a comment --><test2>
+	<?processinginstruction someprocessinginstruction1?>
+	<?processinginstruction someprocessinginstruction2?>
+	<?processinginstruction someprocessinginstruction3?>
+	<?processinginstruction someprocessinginstruction4?>
+	<!-- This is a comment1 -->
+	<!-- This is a comment2 -->
+	<!-- This is a comment3 -->
+	<nonEmptyElement1 emptyAttribute2="" emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement1>
+
+	<nonEmptyElement2 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement2>
+
+	<nonEmptyElement3 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement3>
+
+	<nonEmptyElement4 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement4>
+
+	<nonEmptyElement5 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement5>
+</test2></test3><testCXDM><?processinginstruction someprocessinginstruction?><!-- This is a comment --><test2>
+	<?processinginstruction someprocessinginstruction1?>
+	<?processinginstruction someprocessinginstruction2?>
+	<?processinginstruction someprocessinginstruction3?>
+	<?processinginstruction someprocessinginstruction4?>
+	<!-- This is a comment1 -->
+	<!-- This is a comment2 -->
+	<!-- This is a comment3 -->
+	<nonEmptyElement1 emptyAttribute2="" emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement1>
+
+	<nonEmptyElement2 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement2>
+
+	<nonEmptyElement3 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement3>
+
+	<nonEmptyElement4 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement4>
+
+	<nonEmptyElement5 emptyAttribute="" nonEmptyAttribute="someattrvalue">
+		<emptyElement/>
+		<textElement>sometext</textElement>
+	</nonEmptyElement5>
+</test2></testCXDM></result>
\ No newline at end of file

=== added directory 'test/rbkt/Queries/zorba/identifiers'
=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers.xqlib'
--- test/rbkt/Queries/zorba/identifiers/identifiers.xqlib	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers.xqlib	2011-09-28 09:26:25 +0000
@@ -0,0 +1,3 @@
+module namespace idd= "http://www.zorba-xquery.com/identifiers";;
+
+declare variable $idd:node:=<root><child>text</child></root>;

=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_1.xq'
--- test/rbkt/Queries/zorba/identifiers/identifiers_1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_1.xq	2011-09-28 09:26:25 +0000
@@ -0,0 +1,15 @@
+import module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+
+variable $node:=<root><child>text</child></root>;
+
+variable $before-hasid:=id:has-identifier($node);
+variable $before-currentid:=id:node-identifier($node);
+variable $got:=id:node-identifier($node);
+variable $after-hasid:=id:has-identifier($node);
+variable $after:=id:node-identifier($node);
+
+<result>
+<before hasid="{$before-hasid}">{fn:string-length($before-currentid)}</before>
+<after hasid="{$after-hasid}">{fn:string-length($got)}</after>
+<stable>{$got eq $after}</stable>
+</result>
\ No newline at end of file

=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_2.xq'
--- test/rbkt/Queries/zorba/identifiers/identifiers_2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_2.xq	2011-09-28 09:26:25 +0000
@@ -0,0 +1,21 @@
+import module namespace idd = "http://www.zorba-xquery.com/identifiers"; at "identifiers.xqlib";
+import module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+
+
+declare function local:test()
+{
+  let $node:=<root><child>text</child></root>
+  return id:node-identifier($node)
+};
+
+variable $node:=<root><child>text</child></root>;
+variable $id1:=id:node-identifier($idd:node);
+variable $id2:=local:test();
+variable $id3:=id:node-identifier($node);
+
+
+<result>
+<out-of-module>{id:node-by-identifier($id1)}</out-of-module>
+<temporary-variable>{id:node-by-identifier($id2)}</temporary-variable>
+<in-scope>{id:node-by-identifier($id3)}</in-scope>
+</result>
\ No newline at end of file

=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_3.xq'
--- test/rbkt/Queries/zorba/identifiers/identifiers_3.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_3.xq	2011-09-28 09:26:25 +0000
@@ -0,0 +1,23 @@
+import module namespace idd = "http://www.zorba-xquery.com/identifiers"; at "identifiers.xqlib";
+import module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+
+
+variable $node:=<root><child>text</child></root>;
+variable $id1:=
+try
+{
+  id:current-node-identifier($node)
+}
+catch ZAPI0090
+{
+  "No current id"
+};
+variable $id2:=id:node-identifier($node);
+variable $id3:=id:current-node-identifier($node);
+
+
+<result>
+<before>{$id1}</before>
+<get>{fn:string-length($id2)}</get>
+<after equal="{$id2 =$id3}">{fn:string-length($id3)}</after>
+</result>
\ No newline at end of file

=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_4.spec'
--- test/rbkt/Queries/zorba/identifiers/identifiers_4.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_4.spec	2011-09-28 09:26:25 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/errors:ZAPI0091

=== added file 'test/rbkt/Queries/zorba/identifiers/identifiers_4.xq'
--- test/rbkt/Queries/zorba/identifiers/identifiers_4.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/identifiers/identifiers_4.xq	2011-09-28 09:26:25 +0000
@@ -0,0 +1,3 @@
+import module namespace id = "http://www.zorba-xquery.com/modules/node-identifier";;
+
+id:node-by-identifier("this is not an id")
\ No newline at end of file