tags:

views:

341

answers:

4

Given the following partial XML document:

<section>
    <entry typeCode="DRIV">
     <act classCode="AT" moodCode="DEF">
      <statusCode code="completed"/>
     </act>
    </entry>
    <entry typeCode="DRIV">
     <act classCode="ACT" moodCode="DEF">
      <statusCode code="completed"/>
     </act>
    </entry>
    <entry typeCode="DRIV">
     <act classCode="ACT" moodCode="DEF">
      <statusCode code="completed"/>
     </act>
    </entry>
    <entry typeCode="DRIV">
     <act classCode="ACT" moodCode="DEF">
      <statusCode code="completed"/>
     </act>
    </entry>

    <section>
     <entry typeCode="DRIV">
      <act classCode="AT" moodCode="DEF">
       <statusCode code="completed"/>
      </act>
     </entry>
     <entry typeCode="DRIV">
      <act classCode="ACT" moodCode="DEF">
       <statusCode code="completed"/>
      </act>
     </entry>
    </section>
</section>

I want to assert that all of the elements that are descendents of the outer <section> element, but not the inner <section> element, have for the classCode attribute the value "ACT".

In other words, given the above example, I don't need to assert the value of the two <act> children in the second <section> element. Also, there can be one or more nested <entry> elements (no maximum).

I tried the following XPath expression,

<xsl:when test="cda:section/cda:entry/cda:act//@classCode='ACT'"/>

If any of the <act> elements has a value for the attribute classCode other than "ACT", the assertion should fail. I am looking for advice on how to change my XPath expression to meet this requirement.

A: 

Hm.

<xsl:when test="cda:section/cda:entry/cda:act/@classcode = 'ACT'" />

Should do what you're looking for.

ScottSEA
This test will return true if **any** `classCode` is "ACT". The OP wants to test for **all** `classCode`s being "ACT".
Ben Blank
+1  A: 

Assuming the context node is the outer <section>'s immediate parent, you can do this with the following test:

<xsl:when test="count(cda:section/cda:entry/cda:act) = count(cda:section/cda:entry/cda:act[@classCode = 'ACT'])">
    <foo/>
</xsl:when>

This works by counting the number of <act> elements belonging to <entry>s which are direct descendants of the <section> (anything in the child <section> is skipped). It then counts the number of <act>s which have a classCode of "ACT" and sees if the two counts match. Because it is impossible for a node to match the second count but not the first, you know that all non-nested descendant <act>s have the proper classCode.

Ben Blank
+4  A: 

You just invert the condition:

<xsl:when test="not(cda:section/cda:entry/cda:act//@classCode != 'ACT')"/>

The expression inside not() will produce true if any @classCode will not be equal to 'ACT'. It will only return false if no @classCode is equal to 'ACT'. And then we invert that as well, and get the desired effect.

Pavel Minaev
A: 

If any of the <act> elements has a value for the attribute classCode other than "ACT", the assertion should fail.

Another variant that may be semantically more obvious:

count(cda:section/cda:entry/cda:act[@classCode != 'ACT']) = 0
Tomalak