2

I was looking at a possible XML-based solution to another question. I'm aware of its accepted answer, which offers sed and python solutions.

The given XML fragment is:

<Names>
    <Name>Luigi</Name>
    <Name>Mario</Name>
    <Name>Peach</Name>
</Names>

and the requirement is to change the <Name/> element names to a sequence <Name1/>, <Name2/>, <Name3/>, etc.

Using xmlstarlet I can rename the <Name/> element values to an fixed value with something like this

xmlstarlet ed -u '//Name' -v 'Another' names.xml

<Names>
  <Another>Luigi</Another>
  <Another>Mario</Another>
  <Another>Peach</Another>
</Names>

And I can even change the element values to an expression with -x (--expr).

But for editing element names themselves there is no -x (--expr) option as an alternative to the -v (--value) option, so I cannot use something like this:

xmlstarlet ed -u '//Name' -x 'concat(., position())' names.xml

Using an XML-aware tool such as xmlstarlet, is it possible to transform the input XML to differentiate the <Name/> elements like this, and if so, how?

<Names>
    <Name1>Luigi</Name1>
    <Name2>Mario</Name2>
    <Name3>Peach</Name3>
</Names>
4
  • This should be doable via XSLT, but not trivial. Commented Nov 10, 2017 at 23:47
  • @IgnacioVazquez-Abrams I thought it might be possible with XSLT but I don't know enough about it to know where to begin. It just seems strange that to edit XML I should have to revert to a non-XML-aware tool such as sed! Commented Nov 10, 2017 at 23:48
  • You shouldn't have to. XSLT does have the ability to emit arbitrary tags, but you'll probably have to recurse templates in order to get the numbering. Commented Nov 10, 2017 at 23:49
  • This isn't anything specific to Unix or Linux. Commented Nov 11, 2017 at 0:03

1 Answer 1

2

My experience with XML command-line tools has left me with the feeling that there's a lot to be desired. Almost without fail I find myself giving up and just using Python. That said, I think I have an XQuery solution to this problem that works with the basex utility. Here is the XQuery expression:

<!-- xml_rename_sequence.xquery -->
for $name at $position in doc('names.xml')//Name
return rename node $name as concat(name($name),$position)

And here is the XML data file:

<!-- names.xml -->
<Names>
    <Name>Luigi</Name>
    <Name>Mario</Name>
    <Name>Peach</Name>
</Names>

Here is how we run the script (it modifies the file in-place):

basex -u xml_rename_sequence.xquery

And here is the updated data file:

<!-- names.xml -->
<Names>
  <Name1>Luigi</Name1>
  <Name2>Mario</Name2>
  <Name3>Peach</Name3>
</Names>

I also tried using the following tools (without success):

Here were some posts I found regarding incrementing a counter in XQuery:

And here were some other references I used:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .