1

There may be a better way of doing this and if there is please share. I have a list of ids that I would like to use to select certain elements with. For example lets say I have the following XML

<ANSWER calculatedValue="8917.51" 
        type="DECIMAL" 
        desc="Additional Features"  
        id="ADDTL" />
<ANSWER calculatedValue="1997.16" 
        type="DECIMAL" 
        desc="Appliances"
        id="APP" />
<ANSWER calculatedValue="6988.94" 
        type="DECIMAL" 
        desc="Electrical"
        id="ELE" />
<ANSWER calculatedValue="21184.22" 
        type="DECIMAL" 
        desc="Exterior Finish"
        id="EXT" />

I want to get the sum of the calculatedValues where the ids are ADDTL, APP and ELE. I could do this:

sum(ANSWER[@id = 'ADDTL' or @id = 'APP' or @id = 'ELE']/@calculatedValue)

Is there a way to do something like this:

sum(ANSWER[@id in ('ADDTL,APP,ELE')]/@calculatedValue)

In actual usage this list will be around 15 ids. I could probably use tokenize and index-of to do this but I was wondering if there was something like the SQL "IN" for XPATH. Thoughts, ideas. If worse comes to worse I will just use the "or"s.

testing123
  • 11,367
  • 10
  • 47
  • 61
  • 4
    If you're contemplating tokenize() and index-of() then it must be XPath 2.0. So the answer is to use the "=" operator: when you compare a single value with a sequence, the answer is true if the single value is equal to any item in the sequence. – Michael Kay Feb 16 '11 at 23:55

2 Answers2

3

Almost. Use this XPath 1.0 expression:

sum(
  ANSWER[
    contains(
      ',ADDTL,APP,ELE,',
      concat(
        ',',
        @id,
        ','
      )
    )
  ]/@calculatedValue
)

Or this XPath 2.0 expression:

sum(ANSWER[@id = ('ADDTL','APP','ELE')]/@calculatedValue)
  • @Alejandro I am using XPath 2.0. Apparently sum(ANSWER[@id = ('ADDTL','APP','ELE')]/@calculatedValue) works great. How do I say to only include ANSWER's which have an @id that does not equal one of the ids in the list. I tried this: sum(ANSWER[@id = ('ADDTL','APP','ELE')]/@calculatedValue) but that does not exclude the ANSWER'S like I hoped it would. – testing123 Feb 18 '11 at 22:37
  • @testing123: You need to negate the **existencial comparison**: `sum(ANSWER[not(@id = ('ADDTL','APP','ELE'))]/@calculatedValue)` –  Feb 18 '11 at 22:48
  • What if I want to include look for a tag name. Something like: sum(local-name() = ('ANSWER','GROUP')/@calculatedValue). Right now if I try that I get 'The only functions allowed in a pattern are id() and key()'. Is there a way to do this for tag names? Thank you so much for your help! – testing123 Feb 22 '11 at 20:29
  • @testin123: I think you meant `sum(*[local-name() = ('ANSWER','GROUP')]/@calculatedValue)` –  Feb 22 '11 at 21:28
  • @Alejandro: Great! You have been extremely helpful. What does the *[...] do? I just want to understand better what is going on. Also Is ('ANSWER','GROUP') a node-set? Can I make lists like this from a group of attributes in the xml that is going to be transformed by the xsl? Sorry for being such an xsl noob. I just don't know what to search for so I am having trouble answering these questions. Thank you so much for your willingness to help me! – testing123 Feb 23 '11 at 16:12
  • @testin123: `('ANSWER','GROUP')` is a [sequence](http://www.w3.org/TR/xpath20/#dt-sequence). In XPath 2.0 the expression could be also `sum((*:ANSWER|*:GROUP)/@calculatedValue)`. Ask any time, but in a separate question: other people can have the same doubts. –  Feb 23 '11 at 16:29
  • @Alejandro: Is this:EWT the same as this: ? If so I think that will do the trick for me. I am still curious what these lists are called just so I can know keywords to search for in the future. Are the node-sets? Or are the called something else? – testing123 Feb 23 '11 at 16:45
0

REF: xQuery LIKE-operator?

Community
  • 1
  • 1
kadalamittai
  • 2,076
  • 1
  • 16
  • 19