OS X终端中的XML解析为MobileConfig文件

时间:2015-06-23 06:24:41

标签: ios xml plist mdm apple-configurator

我正在通过bash脚本生成(实际编辑)mobileconfig文件(也就是iOS配置文件,XML)。

脚本从MS数据库中获取数据,现在可以在我的mobileconfig文件(XML)中注入/替换此数据。

XML文件具有以下结构:

<?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>PayloadContent</key>
    <array>
        <dict>
            <key>Host</key>
            <string>outlook.office365.com</string>
            <key>MailNumberOfPastDaysToSync</key>
            <integer>7</integer>
            <key>Password</key>
            <string>ActiveSyncPassword</string>
            <key>PayloadDescription</key>
            <string>Configures an Exchange account</string>
            <key>PayloadDisplayName</key>
            <string>Exchange ActiveSync</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>SSL</key>
            <true/>
            <key>UserName</key>
            <string>xxxxxxx@xxx.com</string>
            <key>disableMailRecentsSyncing</key>
            <false/>
        </dict>
        <dict>
            <key>AutoJoin</key>
            <true/>
            <key>EncryptionType</key>
            <string>WPA</string>
            <key>HIDDEN_NETWORK</key>
            <true/>
            <key>IsHotspot</key>
            <false/>
            <key>Password</key>
            <string>WEPWPAWPSPEAPTLS</string>
            <key>PayloadType</key>
            <string>com.apple.wifi.managed</string>
            <key>PayloadVersion</key>
            <real>1</real>
            <key>ProxyType</key>
            <string>None</string>
            <key>SSID_STR</key>
            <string>SSID</string>
        </dict>
        <dict>

我想更换WiFi密码,还要更换ActiveSync&#34;密码&#34; &之间的字段串GT; &LT; /串GT;使用任何本机(xmllint,sed)或非本机工具。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:3)

使用纯文本工具编辑结构化数据(例如XML),当文件格式以无人希望产生差异的方式(例如插入良性空白)的方式发生变化时,总会以痛苦结束。相反,请使用正确解析XML并在树上工作的工具,例如xmlstarlet

一般形式是

xmlstarlet ed -u xpath -v value filename.xml

其中xpath是标识要更新的节点的XPath表达式,value是您要为其提供的新值。神奇的是构建一个XPath表达式,它唯一且可靠地识别您要更新的节点。 MobileConfig XML格式使这比平常更难。在评论中讨论后我们最终得到了

xmlstarlet ed -u '//dict[key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"]/key[text() = "Password"]/following-sibling::string[1]' -v 'abc123' filename.xml

这是XPath表达式

的核心
//dict[key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"]/key[text() = "Password"]/following-sibling::string[1]

..这需要一些解释。我们使用以下功能:

  • //dict匹配文档中的任何dict节点
  • //dict/key匹配key节点子节点的任何dict节点,
  • //dict/key[text() = "Password"]匹配key节点的子节点dict并且包含文字Password
  • //dict/key[text() = "Password"]/following-sibling匹配此类key节点的任何后续兄弟节点,也就是说,任何节点都是同一父节点的子节点,并且位于XML中的key节点之后,
  • //dict/key[text() = "Password"]/following-sibling::string匹配任何string节点,这是以下兄弟节点,
  • //dict/key[text() = "Password"]/following-sibling::string[1]匹配此类string节点的第一个兄弟key节点之后的任何节点。

我们已经在//dict/key[text() = "Password"]中使用了一个条件;为了找到要更改其密码条目的dict节点,我们需要更多。我们要查找的dict节点由

标识
//dict[key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"]

这是一个满足条件的dict节点

key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"

此条件下的XPath表达式都与正在测试的dict节点相关,因此

key[text() = "PayloadDisplayName"]

指的是key节点的dict子节点,其中包含文本PayloadDisplayName

key[text() = "PayloadDisplayName"]/following-sibling::string[1] = "Exchange ActiveSync"
如果string节点中包含文本key的{​​{1}}节点后面的文本为PayloadDisplayName,则

为true。所以我们把它放到我上面解释的简化表达式中并获得完整的过滤器。

我不得不指出,这个XML文件的结构使得整个事情比必要或通常更难。可以使用更简单的XPath表达式处理Sanely结构化的XML(大多数情况下)。

答案 1 :(得分:1)

你可以这样做

sed -r "s#(<string>)SSID_STR(</string>)#\1AMD\2#g" File

对于原地替换:

sed -i -r "s#(<string>)SSID_STR(</string>)#\1AMD\2#g" File

()用于分组。 \1\2代表firstsecond个此类群组。 将AMD替换为您的实际内容。同样,你可以为密码做。