Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Parsing an XML file

160 views
Skip to first unread message

KP

unread,
Oct 14, 2009, 3:30:25 PM10/14/09
to
Hello,

I'm looking for a simple way to parse and XML file, and use that
information in a tcl script in a useful way.
I have started with tcldom, and parsed an xml file, but can not seem
to do much with it.

Here is a simle xml file contents: (file name is example.xml)
<?xml version="1.0" encoding="UTF-8"?>
<testplan name="regression">
<test name="0.612">
<owner>bob</owner>
<title>Basic Traffic Test</title>
<description>Test supports L2, MPLS and IPV4</description>
<param>test=0.612.1</param>
<instance name="612 random packet length">
<option>pkt_min=64</option>
<option>pkt_max=1518</option>
</instance>
</test>
</testplan>

Now the TCL script to read this in:

package require xml 2.6
package require dom 2.5
package require dom::libxml2
package require xpath
set fp [open "example.xml" r]
set xml [read $fp]
close $fp

puts "xml:\n$xml"

set testplan [dom::parse $xml]
set nodeList [dom::selectNode $testplan /*//*]
foreach node $nodeList {
puts "node:$node";
# puts "node:$node nodeName]; ( <-- get errors here)
}


When I run this I get the following:
xml:
<?xml version="1.0" encoding="UTF-8"?>
<testplan name="regression">
<test name="0.612">
<owner>bob</owner>
<title>Basic Traffic Test</title>
<description>Test supports L2, MPLS and IPV4</description>
<param>test=0.612.1</param>
<instance name="612 random packet length">
<option>pkt_min=64</option>
<option>pkt_max=1518</option>
</instance>
</test>
</testplan>
node:doc0.node0
node:doc0.node1
node:doc0.node2
node:doc0.node3
node:doc0.node4
node:doc0.node5
node:doc0.node6
node:doc0.node7

Anytime I try to do something like get a name I get the following
error:
node:doc0.node0
invalid command name "doc0.node0"
while executing
"$node nodeName"

I know I'm doing something wrong. Any pointers are appreciated.

Thanks,

KP

Aric Bills

unread,
Oct 14, 2009, 6:46:18 PM10/14/09
to

I don't know about tcldom, but here's how you could do it with tDOM:

package require tdom

set file [open example.xml r]
dom parse -channel $file doc ;# doc is a variable which will contain
;# a handle to the DOM tree
set nodeList [$doc selectNodes {/*//*}]
foreach node $nodeList {
puts "node:$node name:[$node nodeName]"
}

Mark Janssen

unread,
Oct 15, 2009, 5:48:01 AM10/15/09
to

Besides the fact that:

puts "node:$node nodeName]

is a syntax error, it looks like you are mixing tcldom with tdom
usage. You are probably looking for:

dom::node configure $node -nodeName

Mark

Robert Heller

unread,
Oct 15, 2009, 8:12:07 AM10/15/09
to
At Wed, 14 Oct 2009 15:46:18 -0700 (PDT) Aric Bills <aric....@gmail.com> wrote:

>
> On 14 oct, 13:30, KP <kplefeb...@gmail.com> wrote:
> > Hello,
> >
> > I'm looking for a simple way to parse and XML file, and use that
> > information in a tcl script in a useful way.
> > I have started with tcldom, and parsed an xml file, but can not seem
> > to do much with it.
> >
> > Here is a simle xml file contents: (file name is example.xml)

> > <?xml version=3D"1.0" encoding=3D"UTF-8"?>
> > <testplan name=3D"regression">
> > <test name=3D"0.612">
> > =A0 <owner>bob</owner>
> > =A0 <title>Basic Traffic Test</title>
> > =A0 <description>Test supports L2, MPLS and IPV4</description>
> > =A0 <param>test=3D0.612.1</param>
> > =A0 <instance name=3D"612 random packet length">
> > =A0 <option>pkt_min=3D64</option>
> > =A0 <option>pkt_max=3D1518</option>
> > =A0 </instance>


> > </test>
> > </testplan>
> >
> > Now the TCL script to read this in:
> >
> > package require xml 2.6
> > package require dom 2.5
> > package require dom::libxml2
> > package require xpath
> > set fp [open "example.xml" r]
> > set xml [read $fp]
> > close $fp
> >
> > puts "xml:\n$xml"
> >
> > set testplan [dom::parse $xml]
> > set nodeList [dom::selectNode $testplan /*//*]
> > foreach node $nodeList {

> > =A0 =A0 puts "node:$node";
> > =A0 =A0 # =A0 puts "node:$node nodeName]; =A0( <-- get errors here)


> >
> > }
> >
> > When I run this I get the following:
> > xml:

> > <?xml version=3D"1.0" encoding=3D"UTF-8"?>
> > <testplan name=3D"regression">
> > <test name=3D"0.612">
> > =A0 <owner>bob</owner>
> > =A0 <title>Basic Traffic Test</title>
> > =A0 <description>Test supports L2, MPLS and IPV4</description>
> > =A0 <param>test=3D0.612.1</param>
> > =A0 <instance name=3D"612 random packet length">
> > =A0 <option>pkt_min=3D64</option>
> > =A0 <option>pkt_max=3D1518</option>
> > =A0 </instance>


> > </test>
> > </testplan>
> > node:doc0.node0
> > node:doc0.node1
> > node:doc0.node2
> > node:doc0.node3
> > node:doc0.node4
> > node:doc0.node5
> > node:doc0.node6
> > node:doc0.node7
> >
> > Anytime I try to do something like get a name I get the following
> > error:
> > node:doc0.node0
> > invalid command name "doc0.node0"

> > =A0 =A0 while executing


> > "$node nodeName"
> >
> > I know I'm doing something wrong. Any pointers are appreciated.
> >
> > Thanks,
> >
> > KP
>
> I don't know about tcldom, but here's how you could do it with tDOM:
>
> package require tdom
>
> set file [open example.xml r]
> dom parse -channel $file doc ;# doc is a variable which will contain
> ;# a handle to the DOM tree
> set nodeList [$doc selectNodes {/*//*}]
> foreach node $nodeList {
> puts "node:$node name:[$node nodeName]"
> }
>

I used the tclxml package in my RPGDB V3.0 code. For this, you need to
define three (at least) functions, an elementstartcommand (called for
<tag ...>), an elementendcommand (called for </tag>), and
characterdatacommand (called for between <tag ...> and </tag>). I put
the code into a snit widget (a type or widgetadaptorwould also work)
and defined (type)methods for these commands. I had type/instance
variables for maintaining a stack of tags (pushed by
elementstartcommand (if not a <tag ... /> form), poped by
elementendcommand) and characterdatacommand used the top of the stack
to see what to do with the data it had.

Feel free to download the source code at
http://www.deepsoft.com/roleplayingdb/downloadrpg and have a look.

--
Robert Heller -- 978-544-6933
Deepwoods Software -- Download the Model Railroad System
http://www.deepsoft.com/ -- Binaries for Linux and MS-Windows
hel...@deepsoft.com -- http://www.deepsoft.com/ModelRailroadSystem/

Steve Ball

unread,
Oct 18, 2009, 7:11:39 PM10/18/09
to
Hi KP,

Firstly, I'd suggest upgrading to TclXML v3.2. Version 2.6 of the
package is quite ancient now.

Your simple application is trying to parse an XML document into a DOM
tree and then iterate over every element node in the tree, displaying
each node's element name. Here's a small script to do that:

package require xml 3.2

set ch [open "example.xml"]
set doc [dom::parse [read $ch]] ;# omitting use of -baseuri option
close $ch

foreach node [dom::selectNode $doc //*] {
puts "node (token $node) name [$node cget -nodeName]"
}

HTHs,
Steve Ball

Steve Ball

unread,
Oct 18, 2009, 7:23:50 PM10/18/09
to
The OP specifically is looking for help with the use of TclDOM, rather
than the streaming, SAX-style interface to TclXML. I've posted a reply
on that basis.

To clarify, the streaming interface has certain advantages but, IMO,
overall it is easier to script using a tree interface (ie. DOM). This
is because the context of an element or text in an XML document is
very important, and the DOM interface preserves the context. With the
streaming interface, it is up to your script code to capture the
context of each element and piece of text.

As an example, here's the solution of the original problem using the
streaming interface:

package require xml

proc eStart {name attrs args} {
puts "node name $name"
}

set parser [xml::parser -elementstartcommand eStart]

set ch [open "example.xml"]
$parser parse [read $ch]
close $ch

With a very simple application there is very little difference, in
terms of LOC, between the two solutions. However, the difference
becomes very apparent once the app becomes a little more complex.

HTHs,
Steve Ball

On Oct 15, 11:12 pm, Robert Heller <hel...@deepsoft.com> wrote:

> Feel free to download the source code athttp://www.deepsoft.com/roleplayingdb/downloadrpgand have a look.


>
> --
> Robert Heller             -- 978-544-6933

> Deepwoods Software        -- Download the Model Railroad Systemhttp://www.deepsoft.com/ -- Binaries for Linux and MS-Windows
> hel...@deepsoft.com       --http://www.deepsoft.com/ModelRailroadSystem/- Hide quoted text -
>
> - Show quoted text -

0 new messages