XMLStarlet:使用xpath将一个元素移动到另一个元素之前

XMLStarlet:使用xpath将一个元素移动到另一个元素之前,xml,xpath,xmlstarlet,Xml,Xpath,Xmlstarlet,鉴于: 产生: echo .. | xml ed -m "//d" "//e" 将放在末尾,但位置不正确 我试着让前面的兄弟姐妹工作(如果这确实是正确的方法),但是: echo .. | xml ed -m "//d" "//x" 结果在中,该查询不能作为移动目的地工作(它抱怨移动目的地不是单个节点),实际上也不能,因为最好的情况是它会在中结束 我不确定ed-m是否是错误的方法,也不确定是否有一种XPATH形式指向元素之间的位置而不是元素 Edit:有趣的是,insert的工作方式更像我所期

鉴于:

产生:

echo .. | xml ed -m "//d" "//e"
放在末尾,但位置不正确

我试着让前面的兄弟姐妹工作(如果这确实是正确的方法),但是:

echo .. | xml ed -m "//d" "//x"
结果在
中,该查询不能作为移动目的地工作(它抱怨移动目的地不是单个节点),实际上也不能,因为最好的情况是它会在
中结束

我不确定
ed-m
是否是错误的方法,也不确定是否有一种XPATH形式指向元素之间的位置而不是元素

Edit:有趣的是,insert的工作方式更像我所期望的,在使用xpath拾取的元素之前插入您传递给它的内容:

echo .. | xml sel -t -c "//e/preceding-sibling::*[1]"
$xml ed-i”//c“-t elem-n“foo”-v“bar”test.xml
酒吧

不幸的是,传递的值(
上面的bar
)不能是XML,所以我可以用sel从某处选择它,然后用这个我不认为是的命令将它注入。

这似乎应该很容易使用
ed
。如果是的话,我没有看到。(我不经常使用xmlstarlet。)

您可能需要使用XSLT

XSLT1.0

$ 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>

命令行

$xml tr test.xsl test.xml

这看起来应该很容易。如果是的话,我没有看到。您是否愿意将XSLT与xmlstarlet一起使用?在XSLT中很容易。“达尼尔哈利,这是真的……我没有考虑只写XSLT MySelfWiw。实际上,我试图替换一些<代码> SED代码,这是一个非常棘手的问题,它的基础是移动一个元素,因为<代码> SED代码太疯狂了,除非运行它,否则我无法真正理解它所做的。
echo .. | xml sel -t -c "//e/preceding-sibling::*[1]"
$ 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>
<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>