Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > List all elements in xml with full paths

Reply
Thread Tools

List all elements in xml with full paths

 
 
fazl.rahman@volcanomail.com
Guest
Posts: n/a
 
      06-20-2008
Hi

I've not been able to find nor concoct a simple filter to convert an
xml file into a list of all its elements (with full paths). This
seems to be a simple requirement...!

As an example I would like this input ...:

<?xml version="1.0"?>
<Person>
<FirstName>Elvis</FirstName>
<LastName>Presley</LastName>
</Person>

....To result in this output :

/Person
/Person/FirstName
/Person/LastName

Any gurus care to share a concise xsl that does this ?

I happened across the 'navigation shell' feature of xmllint during my
fumbling attempts recently - so, lacking a suitbale xslt script, I
guess I could resort to post-processing the output of the shell's "du"
command, which looks like this:

$ xmllint --shell Person.xml
/ > du
/
Person
FirstName
LastName

(If the navigating shell from xmllint incorporated a unix-like 'find'
command, sheesh.. that would be so cool.)

Appreciate (any friendly feedback..
Thanks, Fazl




 
Reply With Quote
 
 
 
 
Martin Honnen
Guest
Posts: n/a
 
      06-20-2008
wrote:

> I've not been able to find nor concoct a simple filter to convert an
> xml file into a list of all its elements (with full paths). This
> seems to be a simple requirement...!
>
> As an example I would like this input ...:
>
> <?xml version="1.0"?>
> <Person>
> <FirstName>Elvis</FirstName>
> <LastName>Presley</LastName>
> </Person>
>
> ...To result in this output :
>
> /Person
> /Person/FirstName
> /Person/LastName
>
> Any gurus care to share a concise xsl that does this ?


Well what do you want to generate if there are namespaces used? What do
you want to generate if there are several FirstName and/or LastName
child elements?

--

Martin Honnen
http://JavaScript.FAQTs.com/
 
Reply With Quote
 
 
 
 
Jürgen Kahrs
Guest
Posts: n/a
 
      06-20-2008
wrote:

> I've not been able to find nor concoct a simple filter to convert an
> xml file into a list of all its elements (with full paths). This
> seems to be a simple requirement...!
>
> As an example I would like this input ...:
>
> <?xml version="1.0"?>
> <Person>
> <FirstName>Elvis</FirstName>
> <LastName>Presley</LastName>
> </Person>
>
> ...To result in this output :
>
> /Person
> /Person/FirstName
> /Person/LastName
>


You might consider using XMLgawk:

$ xgawk -lxml 'XMLSTARTELEM {print XMLPATH}' persons.xml
/Person
/Person/FirstName
/Person/LastName
 
Reply With Quote
 
Jürgen Kahrs
Guest
Posts: n/a
 
      06-20-2008
Correctly indented, it should look like this:

$ xgawk -lxml 'XMLSTARTELEM {print XMLPATH}' persons.xml
/Person
/Person/FirstName
/Person/LastName
 
Reply With Quote
 
fazl.rahman@volcanomail.com
Guest
Posts: n/a
 
      06-21-2008
On 20 Jun., 18:16, Martin Honnen <mahotr...@yahoo.de> wrote:
> Well what do you want to generate if there are namespaces used? What do
> you want to generate if there are several FirstName and/or LastName
> child elements?


I think I'd like to see this kind of output (if these elements are in
a namespace Foo)

Eg:

/
/Fooerson
/Fooerson/FirstName
/Fooerson/LastName

If there are several child elements, I want to see them all listed in
document order.

-Fazl
 
Reply With Quote
 
fazl.rahman@volcanomail.com
Guest
Posts: n/a
 
      06-21-2008
On 20 Jun., 18:15, "szomiz" <szo...@kocha.dostawac.reklamy.przez.net>
wrote:
> <xsl:for-each select="ancestor-or-self::*">
> * * <xsl:value-of select="concat('/',name())"/>
> * * <!--xsl:value-of
> select="concat('[',count(preceding-sibling::*[name()=name(current())])+1,']*')"/-->
>
> sz.


I tried wrapping this suggestion in an <xsl:transform> tag and invoked
it thus:

$ xsltproc.exe pathify.xsl Person.xml

Well, a blank line comes out.



Then I noticed that your for-each tag is missing it's closing tag.

Adding that, and adding a <xsl:template> container too also gives no
output.

Is this the kind of xslt script you mean by your code snippet ?

<?xml version="1.0"?>
<xsl:transform xmlnssl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xslutput method="text"/>
<xsl:template match="*">

<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/',name())"/>
</xsl:for-each>

</xsl:template>
</xsl:transform>


(If you tested it, can you share the actual script with us ?)

What am I doing wrong ?

Fazl
 
Reply With Quote
 
fazl.rahman@volcanomail.com
Guest
Posts: n/a
 
      06-21-2008
On 21 Jun., 03:15, fazl.rah...@volcanomail.com wrote:
> On 20 Jun., 18:15, "szomiz" <szo...@kocha.dostawac.reklamy.przez.net>

[...]
> Then I noticed that your for-each tag is missing it's closing tag.

[...]
> What am I doing wrong ?


After a little tinkering (xsltproc's -v switch is useful), the
transform below delivers what i wanted. (BTW I expect to find this
useful to quickly check whether an element with a given name appears
in a large xml file and if so, at what level of nesting.)

I had to put your code in an xsl:template matching "node()" and
calling itself on the current node's contents after performing it's
ancestral rites. Note the xsl:text element I added to force a new
line for each new element output - Is there a cleaner way to do
this ?

I don't like having to break the indentation of the script, but if I
line up the end tag with the start tag it indents the output by the
same amount of space.

Thanks, Fazl

PS Here's how it looks now:

fazl@ubuntu:~/bin/xslt$ cat Person.xml
<?xml version="1.0"?>
<Person>
<FirstName>Elvis</FirstName>
<LastName>Presley</LastName>
</Person>

fazl@ubuntu:~/bin/xslt$ cat szomiz.xsl
<?xml version="1.0"?>
<xsl:transform xmlnssl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xslutput method="text" />

<xsl:template match="node()">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/',name())"/>
</xsl:for-each>
<xsl:text>
</xsl:text>

<xsl:apply-templates select="*"/>
</xsl:template>

</xsl:transform>

fazl@ubuntu:~/bin/xslt$ xsltproc szomiz.xsl Person.xml
/Person
/Person/FirstName
/Person/LastName

 
Reply With Quote
 
fazl.rahman@volcanomail.com
Guest
Posts: n/a
 
      06-22-2008
On 21 Jun., 16:43, "szomiz" <szo...@kocha.dostawac.reklamy.przez.net>
wrote:
> <xsl:template match="*">
> * * <xslaram name="parPath"/>
> * * <xsl:variable name="locPath" select="concat($parPath,'/',name())"/>
> * * <xsl:value-of select="concat($locPath,' &#10')"/>
> * * <xsl:apply-templates>
> * * * * <xsl:with-param name="parPath" select="$locPath"/>
> * * </
> </


Well, I don't want to sound too ungrateful but this doesn't really
appeal over the one I managed to put together (with help from your
earlier hint - thanks).

- It's not shorter.
- Its not simpler.
- And its not working...



Beyond the broken (obviously, even to me) closing tags, semicolons
seem to be missing in the newline reference.

In fact, simply replacing my:

<xsl:text>
</xsl:text>

with :

<xsl:text> </xsl:text>

is enough ( and not only is shorter, it also works


> [node()] = [* or text() or comment() or processing-instrction()]


This I *didn't* know. So in XSLT, * means something less general than
node() ?

I find this less than intuitive, *surprising* is the word.

But the funniest thing is, to spit out a list of all directories
under / in unix, all you need type is :

find / -type d

Now, XML is basically a tree of elements encoded in text form -- and
XSLT is supposed to be the 'native' way to process XML, yet it takes
an 8-line template (embedded inside a four-line wrapper to make it a
script) to do this simple task.

(Actually I don't mind the number of lines so much as the fact that it
just looks greek compared to "list all element xpaths".)

Am I the only one who suspects there is something rotten in the land
of XSLT ?
(Am I going to get flamed for heretical talk ?

Anyway, I'd be interested if anyone can put together a 'better' xslt
version than below ?
(Better includes 'shorter', 'easier to understand', but not 'really
cool AND really cryptic'..).

fazl@ubuntu:~/bin/xslt$ cat szomiz.xsl
<?xml version="1.0"?>
<xsl:transform xmlnssl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xslutput method="text" />

<xsl:template match="*">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/',name())"/>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:apply-templates select="*"/>
</xsl:template>
</xsl:transform>

fazl@ubuntu:~/bin/xslt$ cat Person.xml
<?xml version="1.0" standalone='yes'?>
<Person>
<FirstName>Elvis</FirstName>
<LastName>Presley</LastName>
</Person>

fazl@ubuntu:~/bin/xslt$ xsltproc szomiz.xsl Person.xml
/Person
/Person/FirstName
/Person/LastName


Thanks, Fazl
 
Reply With Quote
 
Hermann Peifer
Guest
Posts: n/a
 
      06-23-2008
wrote:
>
> I find this less than intuitive, *surprising* is the word.
>
> But the funniest thing is, to spit out a list of all directories
> under / in unix, all you need type is :
>
> find / -type d
> (...)
>
> Am I the only one who suspects there is something rotten in the land
> of XSLT ?
> (Am I going to get flamed for heretical talk ?
>


If you feel that XSLT might not be the best choice for this task, you could give it a try with xmlgawk and use the one-liner (half-liner posted earlier by Juergen:

xgawk -lxml 'XMLSTARTELEM {print XMLPATH}'

For me, this comes closest to your find command example.

Hermann
 
Reply With Quote
 
Peter Flynn
Guest
Posts: n/a
 
      06-24-2008
wrote:
> On 20 Jun., 18:16, Martin Honnen <mahotr...@yahoo.de> wrote:
>> Well what do you want to generate if there are namespaces used? What do
>> you want to generate if there are several FirstName and/or LastName
>> child elements?

>
> I think I'd like to see this kind of output (if these elements are in
> a namespace Foo)
>
> Eg:
>
> /
> /Fooerson
> /Fooerson/FirstName
> /Fooerson/LastName
>
> If there are several child elements, I want to see them all listed in
> document order.
>
> -Fazl


If you don't have xmlgawk, this works with SP and regular awk or gawk:

$ onsgmls -wxml xml.dcl myfile.xml | grep '^[()]' | awk '/\(/ {path=path
"/" substr($0,2)} /\)/ {x=gsub("/[^/]+$","",path)} {print path}'

///Peter
--
XML FAQ: http://xml.silmaril.ie
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Paths, gentleman, paths Ohad Lutzky Ruby 2 11-07-2006 02:15 AM
Removing elements from a list that are elements in another list Adam Hartshorne C++ 2 01-27-2006 07:47 AM
Expanding a perl regex to a list of files with full paths Neil Shadrach Perl Misc 2 10-28-2003 03:14 PM
create foldertree from list of full paths, how? Bart Plessers \(artabel\) ASP General 0 09-30-2003 11:38 AM
Convert between Windows style paths and POSIX style paths Noah Python 5 07-11-2003 09:25 PM



Advertisments