0
votes
<?xml version="1.0" encoding="utf-8" ?>
<menu>
  <group Text="Group1">
    <item Text="Menu1" />
    <item Text="Menu2" Authenticated="0" />
    <item Text="Menu3" />
  </group>
  <group Text="Group2" Authenticated="1">
    <item Text="Menu4" />
    <item Text="Menu5" />
    <item Text="Menu6" />
  </group>
  <group Text="Group3" Authenticated="0">
    <item Text="Menu7" />
    <item Text="Menu8" />
    <item Text="Menu9" />
  </group>
</menu>

On the above xml I want to return all the group elements with their child nodes (item elements) but not those that have the attribute Authenticated equal to '0'

The result should be like this:

  <group Text="Group1">
    <item Text="Menu1" />
    <item Text="Menu3" />
  </group>
  <group Text="Group2" Authenticated="1">
    <item Text="Menu4" />
    <item Text="Menu5" />
    <item Text="Menu6" />
  </group>

*Edit: I have tried the following xpath

/menu/group[not(@Authenticated) or @Authenticated = '1'][item[not(@Authenticated) or @Authenticated = '1']]

but it returns the element

<item Text="Menu2" Authenticated="0" />

which I don't want in the result.

2
What have you tried? From the title, I suppose something related with SimpleXMLElement::xpath. Could you add it to your question? - A. Rodas
I have added the xpath i tried and the item that is not desired in the result. - net_L

2 Answers

0
votes

I don't think there's a way with XPath to get exactly what you're looking for, but what if you just got the group of items that were authenticated like so:

/menu/group/item[@Authenticated!='0' or not(@Authenticated)]

And get back something like this?

<menu>
  <item Text="Menu1"/>
  <item Text="Menu3"/>
  <item Text="Menu4"/>
  <item Text="Menu5"/>
  <item Text="Menu6"/>
  <item Text="Menu7"/>
  <item Text="Menu8"/>
  <item Text="Menu9"/>
</menu>

UPDATE:

Ah, I think I understand what you're aiming at now. Try this:

/menu/group/item[(@Authenticated!='0' or not(@Authenticated)) and (../@Authenticated!='0' or not(../@Authenticated))]

and you should get:

<menu>
  <item Text="Menu1"/>
  <item Text="Menu3"/>
  <item Text="Menu4"/>
  <item Text="Menu5"/>
  <item Text="Menu6"/>
</menu>
0
votes

I don't think this is possible in pure XPath, at least not XPath 1. I would probably just clone the XML and run an XPath to remove //*[@Authenticated=0], leaving you with your desired results but via a more roundabout method.