XMLStarlet: using xpath to move an element in front of another

Given:

<x>
  <a />
  <d />
  <b />
  <c />
  <e />
  <f />
</x>

      

I would like to use xmlstarlet to navigate <d />

to <e />

.

The closest I have is this:

echo .. | xml ed -m "//d" "//e"

      

What produces:

<e>
  <d/>
</a>

      

This is, unfortunately, an example the guide gives.

echo .. | xml ed -m "//d" "//x"

      

Places <d />

at the end, which is not the correct place.

I tried to get it preceding-sibling

to work (if it really is), but while:

echo .. | xml sel -t -c "//e/preceding-sibling::*[1]"

      

Results in <c />

, this query does not work as a move destination (it complains that the destination is not one of a node) and it really is not, as the best case would be that it ends up inside <c />

.

I'm not sure what ed -m

is the wrong approach if there is an XPATH form that points to a location between elements, not with an element.

Edit: Interesting to insert is more like what I expected, inserting what you are passing in front of the element selected with xpath:

$ xml ed -i "//c" -t elem -n "foo" -v "bar" test.xml
<?xml version="1.0"?>
<x>
  <a/>
  <d/>
  <b/>
  <foo>bar</foo>
  <c/>
  <e/>
  <f/>
</x>

      

Unfortunately, the value passed ( bar

above) cannot be XML, so I could select it somewhere with sel and then enter it using this command, I don't think.

+3


source to share


1 answer


It seems like it should be easy with ed

. If so, I don't see it. (I don't use xmlstarlet very often.)

You may need to use XSLT ...

XSLT 1.0



<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()[not(self::d)]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="c">
    <xsl:copy-of select="."/>
    <xsl:copy-of select="../d"/>
  </xsl:template>

</xsl:stylesheet>

      

Command line

$ xml tr test.xsl test.xml
<?xml version="1.0"?>
<x>
  <a/>
  <b/>
  <c/>
  <d/>
  <e/>
  <f/>
</x>

      

+1


source







All Articles