Search code examples
xmlmacosinfo.plistxmlstarlet

info.plist - xmlstarlet does not return specified node


I am attempting to parse an info.plist (for an iOS app) using xmlstartlet. I'm doing this in OSX on a MacBook Pro. Here is my info.plist:

<?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>UIRequiresFullScreen</key>
    <true/>
    <key>ITSAppUsesNonExemptEncryption</key>
    <false/>
    <key>UIDeviceFamily</key>
    <array>
        <integer>1</integer>
        <integer>2</integer>
    </array>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
        <string>UIInterfaceOrientationPortrait</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>MinimumOSVersion</key>
    <string>9.3</string>
    <key>CFBundleDisplayName</key>
    <string>My iOS App</string>
    <key>CFBundleIdentifier</key>
    <string>local.nowhere.MyiOSApp</string>
    <key>CFBundleShortVersionString</key>
    <string>3.3.0</string>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    <key>UISupportedExternalAccessoryProtocols</key>
    <key>UIBackgroundModes</key>
    <array>
        <string>external-accessory</string>
    </array>
    <key>UIAppFonts</key>
    <array>
        <string>FontAwesome.ttf</string>
    </array>
    <key>CFBundleVersion</key>
    <string>321</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <array>
        <string>Location enabled?</string>
    </array>
    <key>NSCameraUsageDescription</key>
    <string>needs access to the camera</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>needs access to photos</string>
    <key>NSCalendarsUsageDescription</key>
    <string>needs access to the calendar</string>
    <key>NSBluetoothPeripheralUsageDescription</key>
    <string>needs access to bluetooth</string>
    <key>UIStatusBarStyle</key>
    <string>UIStatusBarStyleLightContent</string>
    <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>
    <key>XSAppIconAssets</key>
    <string>Resources/Media.xcassets/AppIcons.appiconset</string>
    <key>XSLaunchImageAssets</key>
    <string>Resources/Media.xcassets/LaunchImages.launchimage</string>
</dict>
</plist>

Here is my xmlstarlet command:

xmlstarlet sel -t -m "/plist/dict[key='CFBundleVersion']" -v string ./Info.plist

Here is the output:

Attempt to load network entity http://www.apple.com/DTDs/PropertyList-1.0.dtd
9.3
My iOS App
local.nowhere.MyiOSApp
3.3.0
321
needs access to the camera
needs access to photos
needs access to the calendar
needs access to bluetooth
UIStatusBarStyleLightContent
Resources/Media.xcassets/AppIcons.appiconset
Resources/Media.xcassets/LaunchImages.launchimage

Any ideas why it's returning all 'string' nodes at that level?


Solution

  • You're matching dict and getting the value of string so it's returning all the strings in dict.

    The check to see if there is a key element with the value CFBundleVersion doesn't do anything other than only select the dict if that's true.

    Try selecting the key itself and then getting the value of the first following-sibling string...

    xmlstarlet sel --net -t -m "/plist/dict/key[.='CFBundleVersion']" -v "following-sibling::string[1]" ./Info.plist
    

    This will return:

    321