Difference between revisions of "Tdom"

From AOLserver Wiki
Jump to navigation Jump to search
(imported from WiKit id 253)
 
(#REDIRECT tDOM)
 
Line 1: Line 1:
Documentation is available at http://www.tdom.org/doc-index.html
+
#REDIRECT [[tDOM]]
 
 
A very helpful tutorial is available at http://wiki.tcl.tk/8984
 
 
 
----
 
 
 
[[Dossy]]: [http://www.mail-archive.com/aolserver@listserv.aol.com/msg06871.html Assigning a prefix to the default namespace when using XPath in tDOM]
 
 
 
I don't know how many folks are using tDOM but I'm sure more and more
 
are.  I keep stumbling into this problem of trying to access child nodes
 
which are in the default namespace but the parent is in a named
 
namespace ... and trying to write XPath expressions start to look really
 
dog-awful, like:
 
 
 
    $root selectNodes {/*[[local-name()='foo']]/*[[local-name()='bar']]/...}
 
 
 
So, I sat down for a few minutes and thought about the problem, and
 
after some head-scratching, it hit me: name the default namespace.  Duh.
 
So, here's some sample code:
 
 
 
    ### IMPORTANT: This code lets us get at nodes with a null prefix.
 
    if {[[$root hasAttribute xmlns]]} {
 
        $root setAttributeNS "" xmlns:default [[$root getAttribute xmlns]]
 
    }
 
 
 
So, now, I can rewrite that XPath expression above:
 
 
 
    $root selectNodes /default:foo/default:bar/...
 
 
 
Man.  Life just couldn't get any better.
 
 
 
If any of you are wondering why this matters, here's a sample XML doc
 
and some sample code illustrating the beauty:
 
 
 
    set xml {
 
        <aaa:duh xmlns="booboo" xmlns:aaa="blort">
 
            <foo>
 
                <bar>some text</bar>
 
            </foo>
 
        </aaa:duh>
 
    }
 
 
 
    $doc [[dom parse $xml]]
 
    set root [[$doc documentElement]]
 
 
 
Suppose you want to get the text node inside <bar> with an absolute
 
XPath expression.  You might think you could write:
 
 
 
    [[$root selectNodes /aaa:duh/foo/bar]] text
 
 
 
Ah, but XPath *SPANKS* us and tells us we're naughty, that <foo> and
 
<bar> have a null prefix and live in the unnamed namespace.  That line
 
of code returns an empty string, not "some text" as we might have
 
expected.  So, we tell XPath "well, how about you do me a favor and
 
pretend like any node in the unnamed namespace really has a name of my
 
choosing ..." by doing this:
 
 
 
    $root setAttributeNS "" xmlns:default [[$root getAttribute xmlns]]
 
 
 
We're telling the processor to name all nodes in the default namespace
 
as though they were in the namespace named "default".  N.B.:  If your
 
XML document really *HAS* a namespace named "default", this code will
 
likely CLOBBER it and give you really weird behavior.  Change
 
"xmlns:default" in the above line to a namespace that won't ever exist
 
in your document, then.
 
 
 
Now that we've done this, lets rewrite that XPath expression and try
 
again:
 
 
 
    [[$root selectNodes /aaa:duh/default:foo/default:bar]] text
 
 
 
Ahh!  It returned the string "some text" -- exactly what we wanted.
 
Notice the injection of "default:" above before "foo" and "bar" -- since
 
we just told the processor that nodes in the unnamed namespace (i.e.,
 
<foo> and <bar>) now live in the namespace named "default", in order to
 
specify them in an XPath expression, we need to say "default:foo" and
 
"default:bar".  But this is a hell of a lot easier to read than
 
"*[local-name()='foo']" and "*[local-name()='bar']", at least on my
 
eyes.
 
 
 
If this is all old news, feel free to ignore this email.  I hadn't seen
 
it documented anywhere and I know I've puzzled over this for at least an
 
hour or two over the past few months, so maybe this write-up might save
 
a few people the same agony.
 

Latest revision as of 01:37, 9 October 2005

Redirect to: