Rise_against
Rise_against

Reputation: 1060

XPath & XML modification

I have an XML collection like this:

<test>
   <test1></test1>
   <test2></test2>
   <test3>
      <bla1></bla1>
      <bla2></bla2>
   </test3>
   <test3></test3>
</test>

I want to get all the nodes except for the test3 nodes. I have tried /*[not(name()='test3')], but it does not work.

Also, is it possible with XPath to add a node to an XML collection? How can I do this?

Say I have XML like this:

<rootnode>
  <node1></node1>
</rootnode>

and I want to add another node. How can I do this with XPath, or is this impossible?

I want to get all the nodes except for the test3 nodes (and its innernodes). so if there is a <bla> in test2, I want to get it.

Finally, say that I want to filter the test3 nodes by index. So I want to remove all test3 nodes except for the first one (or the second or third, defined by the index I give).

How would one do this?

Upvotes: 1

Views: 490

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

Now what I want to accomplish is the following, I want to get all the nodes except for the test3 nodes.

Use:

    //node()[not(ancestor-or-self::test3) 
           and 
            not(self::processing-instruction('test3'))] 
   | 
    //*[not(ancestor-or-self::test3)]/@*[not(name()='test3')] 
   | 
    //*[not(ancestor-or-self::test3)]/namespace::*[not(name()='test3')]

Do note that in XPath every element is a node, but not every node is an element. The expression above selects every node in the document, whose name isn't test3 and that has no parent or ancestor named test3.

There are the following types of nodes in the XPath data model:

  1. document-node() (also called "root node) -- selected by / .

  2. element() node, selected by a name test in the child axis, such as child::test3 just test3 or child::* or just * .

  3. text() node, selected by text() .

  4. comment() node, selected by comment()

  5. processing-instruction() node, selected by processing-instruction() or by processing-instruction('someName') .

  6. attribute() node, selected by a name test on the attribute axis, such as attribute::x or @x or @*.

  7. Namespace node, selected by a name test or a wild card on the namespace axis, such as namespace::x or namespace::*.

Do note: The node- test node() selects any of the above 7 types of nodes (which are allowed on the currently specified or default axis. Without axis specified, node() selects any node of type 1 - 5 above.

Upvotes: 1

Lucero
Lucero

Reputation: 60190

1: You were only searching the root, but not the descendant nodes. Also, the name() check should be avoided because it is unreliable when prefixes and namespaces are being used. Try this:

//*[not(ancestor-or-self::test3)]

2: XPath is querying XML only. However, there ar related technologies such as XSLT and XQuery which allow the transformation of XML. Or you can use a DOM in a programming language where you use XPath to identify the nodes and then operations on the DOM to modify them.

Upvotes: 2

Related Questions