mbeckerle commented on a change in pull request #373:
URL: https://github.com/apache/incubator-daffodil/pull/373#discussion_r417341223



##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNFunctions.scala
##########
@@ -683,26 +683,109 @@ case class FNLocalName1(recipe: CompiledDPath, argType: 
NodeInfo.Kind)
   }
 
   override def run(dstate: DState) {
-    // Save off original state, which is the original
-    // element/node that calls inputValueCalc with fn:local-name
-    //
-    val origState = dstate
+    // Save off original node, which is the original
+    // element/node that calls fn:local-name
+    val savedNode = dstate.currentNode
 
     // Execute the recipe/expression which should
-    // return a node/element whose local-name we want.
-    //
+    // return a node/element whose local-name we want
     recipe.run(dstate)
 
     val localName = dstate.currentElement.name
+    dstate.setCurrentNode(savedNode)
 
     if (localName.contains(":"))
       throw new IllegalArgumentException("fn:local-name failed. " + localName 
+ " is not a valid NCName as it contains ':'.")
 
-    // The original state contains the node/element upon which
-    // fn:local-name was called.  This is where we should set
-    // the value.
-    //
-    origState.setCurrentValue(localName)
+    dstate.setCurrentValue(localName)
+  }
+}
+
+/**
+ * Returns the namespace URI of the name of \$arg as an xs:string
+ * value.
+ *
+ * If the argument is omitted, it defaults to the context item (.).
+ * The behavior of the function if the argument is omitted is
+ * exactly the same as if the context item had been passed as
+ * the argument.
+ *
+ * If the node identified by \$arg is neither an element nor an

Review comment:
       DFDL doesn't have attribute nodes. 
   
   That said, there's some value in pointing out that this doc is taken from 
XPath. So you can either (a) remove mention of attribute nodes herein, or (b) 
point out this scaladoc is taken from that of the very similar XPath function. 

##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNFunctions.scala
##########
@@ -683,26 +683,109 @@ case class FNLocalName1(recipe: CompiledDPath, argType: 
NodeInfo.Kind)
   }
 
   override def run(dstate: DState) {
-    // Save off original state, which is the original
-    // element/node that calls inputValueCalc with fn:local-name
-    //
-    val origState = dstate
+    // Save off original node, which is the original
+    // element/node that calls fn:local-name
+    val savedNode = dstate.currentNode
 
     // Execute the recipe/expression which should
-    // return a node/element whose local-name we want.
-    //
+    // return a node/element whose local-name we want
     recipe.run(dstate)
 
     val localName = dstate.currentElement.name
+    dstate.setCurrentNode(savedNode)
 
     if (localName.contains(":"))
       throw new IllegalArgumentException("fn:local-name failed. " + localName 
+ " is not a valid NCName as it contains ':'.")
 
-    // The original state contains the node/element upon which
-    // fn:local-name was called.  This is where we should set
-    // the value.
-    //
-    origState.setCurrentValue(localName)
+    dstate.setCurrentValue(localName)
+  }
+}
+
+/**
+ * Returns the namespace URI of the name of \$arg as an xs:string
+ * value.
+ *
+ * If the argument is omitted, it defaults to the context item (.).
+ * The behavior of the function if the argument is omitted is
+ * exactly the same as if the context item had been passed as
+ * the argument.
+ *
+ * If the node identified by \$arg is neither an element nor an
+ * attribute node, or it is an element or attribute node whose
+ * expanded-QName is in no namespace, then the function returns
+ * the zero-length xs:string value.
+ *
+ * Otherwise, the result will be the namespace URI of the
+ * expanded-QName of the node identified by \$arg returned as an
+ * xs:string value.
+ *
+ * The following errors may be raised when \$arg is omitted:
+ * - If the context item is absent, dynamic error [err:XPDY002]
+ * - If the context item is not a node, type error [err:XPTY004]

Review comment:
       This comment seems to contradict the statement above that says if the 
node identified by arg is neither an element nor an attribute node... 
zero-length string is the value. This appears to be the implemented behavior as 
evidenced by your test that uses element "e5" which has fn:namespace-uri(0) 
which by passing an int here, makes no sense whatsoever, but you've said it 
returns empty string in that case, which it does.
   
   But 0 is not a node, so this second comment suggests this should be a type 
error. Personally, that sounds right to me. If you pass any value to this thing 
you should get a type error. I think. The argument should either be absent, or 
be a path to a node that exists. 

##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/FNFunctions.scala
##########
@@ -683,26 +683,109 @@ case class FNLocalName1(recipe: CompiledDPath, argType: 
NodeInfo.Kind)
   }
 
   override def run(dstate: DState) {
-    // Save off original state, which is the original
-    // element/node that calls inputValueCalc with fn:local-name
-    //
-    val origState = dstate
+    // Save off original node, which is the original
+    // element/node that calls fn:local-name
+    val savedNode = dstate.currentNode
 
     // Execute the recipe/expression which should
-    // return a node/element whose local-name we want.
-    //
+    // return a node/element whose local-name we want
     recipe.run(dstate)
 
     val localName = dstate.currentElement.name
+    dstate.setCurrentNode(savedNode)
 
     if (localName.contains(":"))
       throw new IllegalArgumentException("fn:local-name failed. " + localName 
+ " is not a valid NCName as it contains ':'.")
 
-    // The original state contains the node/element upon which
-    // fn:local-name was called.  This is where we should set
-    // the value.
-    //
-    origState.setCurrentValue(localName)
+    dstate.setCurrentValue(localName)
+  }
+}
+
+/**
+ * Returns the namespace URI of the name of \$arg as an xs:string
+ * value.
+ *
+ * If the argument is omitted, it defaults to the context item (.).
+ * The behavior of the function if the argument is omitted is
+ * exactly the same as if the context item had been passed as
+ * the argument.
+ *
+ * If the node identified by \$arg is neither an element nor an
+ * attribute node, or it is an element or attribute node whose
+ * expanded-QName is in no namespace, then the function returns
+ * the zero-length xs:string value.
+ *
+ * Otherwise, the result will be the namespace URI of the
+ * expanded-QName of the node identified by \$arg returned as an
+ * xs:string value.
+ *
+ * The following errors may be raised when \$arg is omitted:
+ * - If the context item is absent, dynamic error [err:XPDY002]
+ * - If the context item is not a node, type error [err:XPTY004]
+ *
+ * This function is called when 0 arguments are provided.  We
+ * treat this as if the argument passed was "." to denote self.
+ */
+case class FNNamespaceUri0(recipe: CompiledDPath, argType: NodeInfo.Kind)
+  extends RecipeOpWithSubRecipes(recipe) {
+  override def run(dstate: DState) {
+    // Insist this is non-constant at compile time (to avoid a NPE)
+    if (dstate.isCompile)
+      throw new IllegalStateException()
+
+    // Same as using "." to denote self.
+    val value = dstate.currentNode match {
+      case null => ""
+      case _ => dstate.currentNode.namedQName.namespace.optURI match {
+        case Nope => ""
+        case uri => uri.get.toString
+      }
+    }
+    dstate.setCurrentValue(value)
+  }
+}
+
+/**
+ * Returns the namespace URI of the name of \$arg as an xs:string
+ * value.
+ *
+ * If the node identified by \$arg is neither an element nor an
+ * attribute node, or it is an element or attribute node whose

Review comment:
       Same issue here. No attribute nodes in DFDL.

##########
File path: 
daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/home_schema.dfdl.xsd
##########
@@ -63,4 +63,6 @@
     </xs:complexType>
   </xs:element>
 
+  <xs:element name="e5" type="xs:string" dfdl:inputValueCalc="{ 
fn:namespace-uri(0) }"/>

Review comment:
       So this sure seems like it should be a type error to me. If this doesn't 
cause a type error, then there's a separate bug, because passing any value to 
something that reqiures a NodeInfo.Exists should cause a type error. You can 
create a separate ticket for that, and add a comment here mentioning that 
ticket id so that we can find this test associated with that bug. 

##########
File path: 
daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
##########
@@ -11370,13 +11370,55 @@
       </tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
-  
-<!--
-    Test Name: nilled_01
-       Schema: booleanFunctions
-         Root: nilled01
-      Purpose: This test demonstrates that the fn:nilled function returns true 
if arg is a node with xsi:nil = true
--->
+
+  <!--
+      Test Name: namespace_uri_07
+         Schema: home_schema.dfdl.xsd
+           Root: e5
+        Purpose: This test demonstrates the namespace-uri() function
+  -->
+
+  <tdml:parserTestCase name="namespace_uri_07" root="e5"
+                       model="home_schema.dfdl.xsd" description="Section 23 - 
Functions - fn:namespace-uri() - DFDL-23-126R">
+
+    <tdml:document>
+      <tdml:documentPart type="text"></tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <e5></e5>

Review comment:
       I find it surprising that this produces empty string as value. 




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to