Getting the parent when the child doesn't exist

G

Greg Collins

I'm posting this to both the XSL and C# newsgroups because it spans both.

I have an XPath passed to me that starts at the root node and goes down to a
table row node. From this XPath I was grabbing the table node by appending a
"/.." to the end of the XPath.

While this technique works great when the row exists, if the row does not
exist, I can no longer identify the table node.

In code, one might say, well just rip off everything past the last slash
character. This won't work because I cannot guarantee that a filter is not
being used. And there might be nested filters and "[" and "]" characters
used in the filter as values.

So what I need to find is a way to extrapolate the parent XPath from that
which is passed in, but accounting for potential nested filters and [ ]
characters used as filter values.

Anyone got any ideas? Here's a sample test XPath:

/ns:Root/ns:Branch[ns:Val1 = '[']/ns:Table[ns:Row/ns:Field1 =
'[']/ns:Row[ns:Field2 = '[Test' and ns:Group1/ns:Field3[ns:Val2 = ']'] =
'[']

What I need to get from it is the following:

/ns:Root/ns:Branch[ns:Val1 = '[']/ns:Table[ns:Row/ns:Field1 = '[']

I also cannot count on a namespace existing on the nodes. It might not.

Regex would be great (if even possible). Brute force works too.

Thanks ahead of time for any help.
 
J

Jeroen Mostert

Greg said:
I'm posting this to both the XSL and C# newsgroups because it spans both.

I have an XPath passed to me that starts at the root node and goes down
to a table row node. From this XPath I was grabbing the table node by
appending a "/.." to the end of the XPath.

While this technique works great when the row exists, if the row does
not exist, I can no longer identify the table node.
I don't mean to be overly simplistic, but why don't you just use the XPath
to navigate to the table node and then use the DOM (in an XPathNavigator, or
whatever other guise) to conditionally navigate up? Do you have to stuff it
in a single XPath expression?

Otherwise, yes, you'll probably have to get tricky actually semi-parsing the
XPath -- whip out the standard and away you go. I'd reconsider the entire
approach first, though.
 
J

Jeroen Mostert

Jeroen said:
I don't mean to be overly simplistic, but why don't you just use the
XPath to navigate to the table node and then use the DOM (in an
XPathNavigator, or whatever other guise) to conditionally navigate up?
Do you have to stuff it in a single XPath expression?
Wait, I fail at reading -- you want to find the parent node when the child
node doesn't exist (that particular expression isn't meaningful, but at
least now I get what you mean).

Well, I don't mean to be a spoilsport, but there's no guarantee you can get
at a "parent node" at all in this case, is there? You can't navigate to a
node based on its relation to a node that doesn't exist. Manipulating the
XPath expression that points at the child node won't always work unless you
can really guarantee that the XPath expression will be strictly
hierarchical. Finding what would have been the parent node of "id('test')"
had it existed, for example, is a tad tricky.
 
P

Pavel Minaev

I'm posting this to both the XSL and C# newsgroups because it spans both.

I have an XPath passed to me that starts at the root node and goes down to a
table row node. From this XPath I was grabbing the table node by appending a
"/.." to the end of the XPath.

While this technique works great when the row exists, if the row does not
exist, I can no longer identify the table node.

In code, one might say, well just rip off everything past the last slash
character. This won't work because I cannot guarantee that a filter is not
being used. And there might be nested filters and "[" and "]" characters
used in the filter as values.

So what I need to find is a way to extrapolate the parent XPath from that
which is passed in, but accounting for potential nested filters and [ ]
characters used as filter values.

As Jeroen says, there is no truly generic solution, as an XPath
expression needs not explicitly mention the parent of the child at
all.

If you can guarantee that the expression truly has the form /foo/bar/
baz (i.e. only ever uses child:: axis), and optional filters on every
step, then you can of course just parse that expression and drop the
final part of the path. You might even be able to handle that sort of
parsing with regex, as .NET ones are powerful enough to handle nested
square brackets - for an example, see http://www.m-8.dk/resources/RegEx-nested-constructions.aspx.
Even so, it may be very tricky to get right, and quite likely it is
better to just write a proper XPath parser (only handling the
simplified grammar as described earlier - this will also ensure that,
if something wrong is passed to you, you don't silently parse it
wrong). XPath grammar is fairly simple and unambiguous, so you
shouldn't have a problem a parser generator - COCO/R is neat and very
small, ANTLR is another good and very powerful one, and there are
plenty others.
 
G

Greg Collins

The scenario requires a full root to destination xpath to be passed in, so I
can assume that the table node is actually in the XPath. I use error
handling to determine whether the table node actually exists... but my
current approach of just walking up from the row to the table obviously
fails in the case where no row is present.

Again, the assumption is that the XPath is valid from the root all the way
down to the row (except that there might not be any rows) with error
handling checking actual presense of row and table nodes.

Yes, this is quite tricky, which is why I though I'd post to see if anyone
had done something like this.

I will look at the posting on Regex Nested Constructions to see if it can be
applied to what I'm trying to do. . . though if anyone has done something
like this before (or has a bigger brainstorm than I've had so far) please
respond.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top