0
votes

I want to remove a node from an XML file (using SaxonHE9-8-0-11J):

<project name="Build">
  <property name="src" value="src/main/resources" />
  <property name="target" value="target/classes" />

  <condition property="target.exists">
    <available file="target" />
  </condition>
</project>

Apparently there are 2 ways I can do this. XPath1: using a not function XPath2: using an except clause. But both simply return the entire node-set.

With a not function:

saxonb-xquery -s:test.xml -qs:'*[not(local-name()="condition")]'

With an except clause:

saxonb-xquery -s:test.xml -qs:'* except condition'

With -explain switch the queries are:

<query>
  <body>
    <filterExpression>
      <axis name="child" nodeTest="element()"/>
      <operator op="ne (on empty return true())">
        <functionCall name="local-name">
          <dot/>
        </functionCall>
        <literal value="condition" type="xs:string"/>
      </operator>
    </filterExpression>
  </body>
</query>

and

<query>
  <body>
    <operator op="except">
      <axis name="child" nodeTest="element()"/>
      <path>
        <root/>
        <axis name="descendant" nodeTest="element(condition, xs:anyType)"/>
      </path>
    </operator>
  </body>
</query>
1

1 Answers

1
votes

In general, XPath select nodes from one or more input documents, it doesn't allow you to construct new ones, for that you need XSLT or XQuery. And removing the condition child of the project root, if that is what you want to achieve, is something you need XSLT or XQuery for, with XPath, even if you use /*/(* except condition), you then get all children except the condition element, but as a sequence, not wrapped into a a root.

So with XQuery you could use

/*/element {node-name()} { * except condition }

as a compact but generic way to reconstruct any root with all child elements except the condition: https://xqueryfiddle.liberty-development.net/948Fn5b

Whether you get such an expression through a command line shell is a different problem, on Windows with a Powershell window and the cmd shell it works for me to use

-qs:"/*/element {node-name()} { * except condition }"