Author |
Message
|
BCWolf |
Posted: Thu Jul 04, 2013 12:08 pm Post subject: Determining the XMLNSC namespaces |
|
|
Newbie
Joined: 13 Mar 2013 Posts: 7
|
I am trying to determine how many namespaces are associated with a given MessageAssembly -- but when i use the wildcard character (which according to the docs is supposed to yield a list when used in a node name) i am being given an error message complaining about the lack of list in the operand:
DECLARE nsCount INT CARDINALITY(root.(XMLNSC.NamespaceDecl)*);
where root is a REFERENCE passed into the function.
So how can i count (let alone list, which is what i really want to do) the namespaces associated with a given node? |
|
Back to top |
|
 |
mqjeff |
Posted: Thu Jul 04, 2013 12:15 pm Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
* means anonymous, it doesn't mean list.
You want
Code: |
root.(XMLNSC.NamespaceDecl)*[] |
|
|
Back to top |
|
 |
BCWolf |
Posted: Thu Jul 04, 2013 3:17 pm Post subject: |
|
|
Newbie
Joined: 13 Mar 2013 Posts: 7
|
Thanks -- but now i am even more confused.
Code: |
CARDINALITY(root.(XMLNSC.NamespaceDecl)*[]) |
returns zero, yet
Code: |
FIELDNAMESPACE(root) |
yields the namespace i was expecting to see.
I know there is an associated namespace with the nodes, as i created them that way:
Quote: |
...
<NS1:ReferenceNumber>1</NS1:ReferenceNumber>
<NS1:Adjudication>0</NS1:Adjudication>
<NS1:BirthCertificateNumber>20070004</NS1:BirthCertificateNumber>
|
So why isn't the cardinality function returning 1? |
|
Back to top |
|
 |
fjb_saper |
Posted: Thu Jul 04, 2013 5:54 pm Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
Possibly because you are looking for a formal namespace declaration whereas you defined the element with an implicit one. I.e the formal on will only be created on serialization...
Have fun  _________________ MQ & Broker admin |
|
Back to top |
|
 |
kimbert |
Posted: Fri Jul 05, 2013 12:42 am Post subject: |
|
|
 Jedi Council
Joined: 29 Jul 2003 Posts: 5542 Location: Southampton
|
This
Code: |
CARDINALITY(root.(XMLNSC.NamespaceDecl)*[]) |
will return the number of children under 'root' that have the field type XMLNSC.NamespaceDecl.
This, on the other hand
Code: |
FIELDNAMESPACE(root) |
will tell you the namespace of element 'root'.
If 'root' is the document root then you have a right to be puzzled. But if 'root' is nested within at least one parent tag then the namespace declaration could have been placed on one of its parent tags. |
|
Back to top |
|
 |
mqjeff |
Posted: Fri Jul 05, 2013 6:58 am Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
BCWolf wrote: |
Thanks -- but now i am even more confused.
Code: |
CARDINALITY(root.(XMLNSC.NamespaceDecl)*[]) |
returns zero, yet
Code: |
FIELDNAMESPACE(root) |
yields the namespace i was expecting to see. |
What do you mean, "the namespace you are expecting to see".
You wanted
Quote: |
to determine how many namespaces are associated with a given MessageAssembly |
That's not remotely the same thing as asking for the namespace associated with a specific element.
What, and be specific, are you really trying to at a higher level?
You are constructing a document, building it up element by element, and attaching namespaces to each and every element.
You are then, what, trying to count up the distinct namespaces you have actually already created? How can you have built them if you don't know what they are?
Are you trying to find out which namespaces you need to create explicit namespace declarations for? Again, how can you build your code without knowing that before hand?
Are you trying to normalize an XML message, and make sure it includes namespace declarations for all used namespaces in the document at the root of the document? really? why? And why do you need to count them to do this? |
|
Back to top |
|
 |
BCWolf |
Posted: Fri Jul 05, 2013 10:17 am Post subject: |
|
|
Newbie
Joined: 13 Mar 2013 Posts: 7
|
Thanks for all your replies. Ultimately, what i am trying to do is understand the way a message assembly is organized in an XMLNSC parser, since it is not very clear from the online documentation.
The specific task to hand was to strip the namespaces away from all the nodes in the generated XML stream since the recipient is validating it against a schema without them. I realize the correct course of action would be to create a new MessageSet just for this stream which has namespaces turned off, but i inherited this code and am just trying to make it work with a minimum of coding changes.
Quote: |
What do you mean, "the namespace you are expecting to see".
|
I know that each node in the assembly has an associated explicit namespace, because they are being set using them (and the tags in the generated XML stream show them):
Quote: |
SET trgtVBCRqst.nsEDL_VBC_DP:ReferenceNumber VALUE = srcVBCRqst.nsEDL_VBC:ReferenceNumber; |
Quote: |
<NS1:ReferenceNumber>1</NS1:ReferenceNumber> |
so i would expect each node to have the NS1 namespace associated when i query its properties.
I also realize i don`t really understand the mechanics, because despite
Code: |
SET root.(XMLNSC.NamespaceDecl)nsEDL_VBC_DP = NULL; |
the node retains the associated namespace. I tried it using the wildcard character as well (`remove all associated namespaces', which is why i was trying to count them to see how many there might be -- i was expecting 1).
What a really want is an Advanced WMB guide that gets into the details of how things work under the covers (the advanced course didn't help with that, either) but i have not been able to find such a thing.
Part of my problem is that i come from a Java/C++ background, and many things just don't work as I expect them to (trying to write a recursive tree-walk, for instance, was quite the eye-opener -- references just don't behave as i expect pointers would, which clearly indicates they are some other kind of critter entirely).
Thanks in advance for your help and tolerance. |
|
Back to top |
|
 |
fjb_saper |
Posted: Fri Jul 05, 2013 11:46 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
You are looking at it from an XML point of view: wrong point of view!
Think tree manipulation....
Use a cursor and recursively navigate the tree.
You can check fieldnamespace(cursor) and you can use
Code: |
SET cursor NAMESPACE = ''; |
to remove the namespaces.
Have fun  _________________ MQ & Broker admin |
|
Back to top |
|
 |
mqjeff |
Posted: Fri Jul 05, 2013 12:18 pm Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
References do work as pointers work, mostly.
Every element in the logical message tree has five pointers off of it: Parent, First Child, Last Child, Previous Sibling, Next Sibling. From a given element, those are the only places you can move to.
Any of those can be Null. Moving to a null location is invalid (and causes lastmove to return false).
Each element can hold a Name, a Value, a parser-specific type, and a Namespace.
An XMLNSC document tree will consist of a set of nodes that will have (or not have) namespace declarations set on them, and all have parser-specific types that belong to the XMLNSC Parser. One of those parser-specific types indicates that the element is a Namespace Declaration.
If you look at the Javadoc for the MbElement class in the Java API (here, although that might not work), it should be more informative of what you're dealing with.
Why are you trying to clear the namespace contents of every element of a given message tree? Are you trying to change the physical representation of the message after serialization? Or are you really trying to transform the message from one that has elements that belong to a specific namespace into one that has elements that don't belong to a specific namespace? |
|
Back to top |
|
 |
kimbert |
Posted: Fri Jul 05, 2013 1:04 pm Post subject: |
|
|
 Jedi Council
Joined: 29 Jul 2003 Posts: 5542 Location: Southampton
|
I assume that you read this topic, but just in case you missed it: http://publib.boulder.ibm.com/infocenter/wmbhelp/v7r0m0/index.jsp?topic=%2Fcom.ibm.etools.mft.doc%2Fac67194_.htm
Quote: |
An XMLNSC document tree will consist of a set of nodes that will have (or not have) namespace declarations set on them, and all have parser-specific types that belong to the XMLNSC Parser. One of those parser-specific types indicates that the element is a Namespace Declaration. |
That's accurate, but just in case there is any doubt I would like to make it even clearer:
- Every node in every message tree has a namespace. The namespace might be the empty string.
- In an XMLNSC message tree, every node has the same namespace as it would have in a DOM tree.
- The value of the namespace on every node is a string. It is not the prefix ('NS1') but the full namespace URI for the corresponding tag or attribute.
- Namespace declarations ( sometimes called 'xmlns attributes' ) are also put into the message tree if they occur in the input XML. When the message tree is written to an XML document, the namespace declarations are used to control the prefixes in the output XML.
- Namespace declarations can also be added or deleted by the message flow author to control the prefixes that are written in the output XML. If you add a namespace declaration to a message tree, it does not change the value of the namespace on any other node in the message tree. It may alter the prefixes that are used when writing other nodes - but that was probably the objective.
Hope that helps. |
|
Back to top |
|
 |
BCWolf |
Posted: Mon Jul 08, 2013 11:39 am Post subject: |
|
|
Newbie
Joined: 13 Mar 2013 Posts: 7
|
Thanks again for your informative replies. Much of what you wrote confirms what i had gleaned, but in a clearer and direct way.
Quote: |
Why are you trying to clear the namespace contents of every element of a given message tree? |
Because it is being sent to a DataPower service which is validating the XML stream against a schema that has no associated namespace. However, the original message flow developers choose to put all the schemas into a single MessageSet, so they need namespaces to be able to distinguish them, as they are essentially the same with minor variances (such as an extra status field in one versus the other).
Quote: |
References do work as pointers work, mostly. |
Yes, except when trying to set one to point at the node of another. Then i get an error about being self-referential, since the = operator is defined to mean 'copy the value in the source node pointed at over to the destination node', rather than 'make the target reference point to the source node' -- is there a syntax i can use to achieve the latter? This was a real problem when reaching the leaf node of my recursive tree walk. The ESQL example 2 code avoids this, but what about the case where navigate() was called on a node with no children, only siblings? The MOVE cursor FIRSTCHILD; would cause both subsequent LASTMOVE statements to fail, so that we never iterate across the siblings, would it not? Or does the call to LASTMOVE clear the flag, so that the second call always succeeds? My treewalk code
Code: |
DECLARE currRoot REFERENCE TO root;
MOVE currRoot FIRSTCHILD;
WHILE LASTMOVE(currRoot) DO
-- recurse down the sibling`s subtree
CALL stripNameSpace(currRoot);
-- move to the next sibling
MOVE currRoot NEXTSIBLING;
END WHILE;
|
worked, but i am concerned that it was due to the particular topology of the data tree i applied it to rather than working universally. I also realize i only have one rather than two consecutive LASTMOVE calls as well, so if flag-clearing is indeed involved, this code is broken. |
|
Back to top |
|
 |
mqjeff |
Posted: Mon Jul 08, 2013 12:19 pm Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
I'm reasonably sure that there's a post somewhere here that already shows how to remove all of the namespaces from a tree, recursively.
Regardless, it is just a tree, and you would navigate it recursively either depth first or breadth first as you choose, and instead of checking if the pointer was NULL, you'd check if LASTMOVE was false and then take the appropriate action.
But yes, you need to MOVE reference variables rather than SET = them. |
|
Back to top |
|
 |
BCWolf |
Posted: Mon Jul 08, 2013 1:20 pm Post subject: |
|
|
Newbie
Joined: 13 Mar 2013 Posts: 7
|
Quote: |
I'm reasonably sure that there's a post somewhere here that already shows how to remove all of the namespaces from a tree, recursively. |
My recursive walk, coupled with using SET root NAMESPACE = ''; as the first line in the function, worked just fine -- apart from my concern that it has that flaw regarding reaching siblings of childless nodes. |
|
Back to top |
|
 |
mqjeff |
Posted: Mon Jul 08, 2013 1:41 pm Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
BCWolf wrote: |
Quote: |
I'm reasonably sure that there's a post somewhere here that already shows how to remove all of the namespaces from a tree, recursively. |
My recursive walk, coupled with using SET root NAMESPACE = ''; as the first line in the function, worked just fine -- apart from my concern that it has that flaw regarding reaching siblings of childless nodes. |
Right, ok, I see what you're concerned about.
The tree walk shown is doing a depth first traversal, so it's going to clear out the namespace of the lower-left most leaf node first. Leaf nodes have no children, so the while loop will never be entered, and the function will end. When the function ends, currRoot at the higher recursion will still be pointing to the lower-left most leaf node, and then go to it's next sibling.
In other words, you shouldn't miss anything.
You might want to consider scoping the moves to limit yourself to walking over XMLNSC.Element nodes, rather than dealing with all nodes in the tree regardless of Type. If you know you need to strip namespaces from XMLNSC.Attributes, you might still put in separate logic to handle those directly (another next sibling loop). |
|
Back to top |
|
 |
|