2

Following xml is part of my xml file. I need to get manufacture's name of the cars which do not have maintenance. For small example I have tried following but it workes but when number of cars increase it doesn't return correct output:

@xpath /*/descendant::maintenances[not(maintenance)]/preceding::manufacturer/text()

By the way I tried these as well:

@xpath /descendant::maintenances[not(*)][not(normalize-space())]/preceding::manufacturer/text()


@xpath /descendant::maintenances[not(maintenance)]/preceding::manufacturer/text()

@xpath /descendant::maintenances[not(maintenance())]/preceding::manufacturer/text()

small example:

<vehicles>
        <car rego="XYZ007">
          <manufacturer>Toyota2</manufacturer>
          <model>Camry</model>
          <capacity>5</capacity>
          <maintenances/>
        </car>
        <car rego="ABC123">
          <manufacturer>Toyota</manufacturer>
          <model>Corolla</model>
          <capacity>4</capacity>
          <maintenances>
            <maintenance enum="m0045">
                <mdate>20-JAN-2012</mdate>
                <parts>
                     <part>air filter</part>
                </parts>
                <description>Replaced air filter</description>
            </maintenance>
          </maintenances>
      </car>
</vehicles>

Output: Toyota2

big example:

   <vehicles>
    <bus rego="PKR856">
      <manufacturer>MAN</manufacturer>
      <capacity>52</capacity>
      <maintenances>
          <maintenance enum="m1234">
            <mdate>12-MAR-2009</mdate>
            <parts>
               <part>tire</part>
            </parts>
            <description>Changed tires</description>
        </maintenance>
      </maintenances>
    </bus>
    <bus rego="UUQ007">
      <manufacturer>Volvo</manufacturer>
      <capacity>60</capacity>
      <maintenances>
        <maintenance mnum="m1234">
            <mdate>10-JAN-2001</mdate>
            <parts>
               <part>air filter</part>
               <part>oil filter</part>
               <part>engine oil</part>
              </parts>
              <description>Replaced engine oil, oil filter, and air filter</description>
        </maintenance>
       </maintenances>
    </bus>
    <bus rego="XYZ987">
      <manufacturer>Volvo</manufacturer>
      <capacity>60</capacity>
    </bus>
    <truck>
      <manufacturer>Volvo</manufacturer>
      <capacity>6000</capacity>
      <maintenances>
        <maintenance enum="m1234">
            <mdate>10-JAN-2011</mdate>
            <parts>
               <part>air filter</part>
              </parts>
            <description>Replaced air filter</description>
        </maintenance>
        <maintenance enum="m1234">
            <mdate>13-MAY-2014</mdate>
            <parts>
               <part>fuel pump</part>
                </parts>
            <description>Replaced fuel pump</description>
        </maintenance>
       </maintenances>
    </truck>
        <truck rego="ZZZ777">
       <manufacturer>Kenworth</manufacturer>
       <capacity>5000</capacity>
           <horsepower>38</horsepower>
       <maintenances/>
        </truck>


    <car rego="XYZ007">
      <manufacturer>Toyota</manufacturer>
      <model>Camry</model>
      <capacity>5</capacity>
      <maintenances/>
    </car>



       <car rego="ABC123">
      <manufacturer>Toyota</manufacturer>
      <model>Corolla</model>
      <capacity>4</capacity>
      <maintenances>
        <maintenance enum="m0045">
            <mdate>20-JAN-2012</mdate>
            <parts>
               <part>air filter</part>
                </parts>
            <description>Replaced air filter</description>
        </maintenance>
          </maintenances>
       </car>
    <limousine rego="VVV001">
      <manufacturer>Maserati</manufacturer>
      <capacity>2</capacity>
       </limousine>
       <limousine rego="PKR856">
      <manufacturer>Rolls Royce</manufacturer>
      <capacity>4</capacity>
      <maintenances>
        <maintenance enum="m0001">
            <mdate>12-JUN-2006</mdate>
            <parts>
               <part>ash tray</part>
                </parts>
            <description>Replaced golden ash tray</description>
        </maintenance>
          </maintenances>
       </limousine>
   </vehicles>

Output: all the cars

Bernard
  • 4,240
  • 18
  • 55
  • 88
  • I'm not exactly an xpath master, but have you tried this: http://stackoverflow.com/questions/862239/xpath-get-node-with-no-child-of-specific-type ? – Piotr Miś Jun 01 '14 at 11:42
  • @uraf Yes I saw that. As you can see my other statements doesn't have /*. – Bernard Jun 01 '14 at 11:44

2 Answers2

2

You can try this XPath :

/vehicles/*[maintenances[not(maintenance)]]/manufacturer

With the 2nd XML sample the output is :

<manufacturer>Kenworth</manufacturer>
<manufacturer>Toyota</manufacturer>
har07
  • 88,338
  • 12
  • 84
  • 137
  • A quick question: why does `*[maintenances[not(maintenance)]]` return something different than `*[not(maintenances/maintenance)]`? – Piotr Miś Jun 01 '14 at 12:03
1

This seems to work:

/vehicles/car[not(maintenances/maintenance)]/manufacturer

Output:

<manufacturer>Toyota2</manufacturer>
Piotr Miś
  • 981
  • 5
  • 6