0

The following sample Plist file is used for my question below.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>firstDictionary</key>
    <dict>
        <key>string</key>
        <string>someText</string>
        <key>anArray</key>
        <array>
            <string>first</string>
            <string>second</string>
        </array>
    </dict>
    <key>secondDictionary</key>
    <dict>
        <key>subDictionary</key>
        <dict>
            <key>aBoolValue</key>
            <false/>
        </dict>
    </dict>
</dict>
</plist>

So my question is, since this is a Plist (working with XCode), all keys have the element name <key> and the values can be , , etc... The Key-value pair are always side-by-side (direct siblings)..

Is there a way using XQuery produce the value for a key? Like say retuenValueForKey(secondDictionary) to produce the following?

<dict>
    <key>subDictionary</key>
    <dict>
        <key>aBoolValue</key>
        <false/>
    </dict>
</dict>

My main reference so far is this link from W3Schools, but I could not get it working correctly.

Just a coder
  • 15,480
  • 16
  • 85
  • 138

1 Answers1

1

You can do it in pure XPath, but if you want to wrap it in a function that should work fine too:

declare function local:returnValueForKey(
  $key as xs:string,
  $plist as element(plist)
) as element(dict)?
{
   $plist//key[. = $key]/following-sibling::*[1]/self::dict
};

local:returnValueForKey('secondDictionary', <plist>...</plist>)
=>
<dict>
  <key>subDictionary</key>
  <dict>
    <key>aBoolValue</key>
    <false/>
  </dict>
</dict>
wst
  • 11,681
  • 1
  • 24
  • 39
  • ok. I'm doing up this function to see if i'll understand it but im running into some errors. Does this function work for you as is with the sample plist above? [edit] Function returnValueForKey(...) uses reserved namespace. ok let me mess with it a lil bit – Just a coder Apr 19 '13 at 21:22
  • Sorry, yes, the function has to be in a namespace. Use the fixed example above, or use the namespace prefix of the module that contains the function in place of `local`. – wst Apr 19 '13 at 21:43
  • The method no longer gives error, but it gives no result. I'll wrap my head around XQuery methods later. The method's internal code however works --> **//key[. = $key]/following-sibling::*[1]/self::dict** ... So i'm flagging this as correct. Could explain what that last part means though? --> self::dict – Just a coder Apr 19 '13 at 22:48
  • Sure. `self::dict` selects the context node *only if it's a dict*. It's more of an insurance policy in this case. `following-sibling::*[1]` will always take the immediate following sibling element, and `self::dict` guarantees that it will only return a dict. This pattern is safer because `following-sibling::dict` will return the first following dict, whether or not it is the element immediately following the context node. – wst Apr 19 '13 at 23:01