在nodejs中使用elementtree包,我正在尝试验证xml文件(特别是android清单文件)中是否存在某个xml属性。
var manifestTxt = fs.readFileSync('AndroidManifest.xml', 'utf-8'),
manifestDoc = new et.ElementTree(et.XML(manifestTxt)),
expected = 'application/activity[@android:name="com.whatever.app"]';
test.ok(manifestDoc.find(expected));
我遇到以下异常:
node_modules/elementtree/lib/elementpath.js:210
throw new SyntaxError(token, 'Invalid attribute predicate');
^
Error: Invalid attribute predicate
它似乎不喜欢属性名称中的冒号,但没有它,搜索不匹配。我认为我正在处理命名空间错误 - 但找不到合适的方法。
编辑以下是我正在搜索的示例xml:
<?xml version='1.0' encoding='utf-8'?>
<manifest ... xmlns:android="http://schemas.android.com/apk/res/android">
<application android:debuggable="true" android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:label="@string/app_name" android:name="com.whatever.app">

<intent-filter>
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="5" />
</manifest>
答案 0 :(得分:8)
如果您没有如何注册命名空间并使用相关前缀的信息,请使用:
application/activity
[@*[local-name()=name'
and
namespace-uri() = 'http://schemas.android.com/apk/res/android'
]
=
'com.whatever.app'
]
在一般情况下不安全的简单表达式,但可以在此特定情况下选择所需节点:
application/activity[@*[local-name()='name'] = 'com.whatever.app']
或此表达:
application/activity[@*[name()='android:name'] = 'com.whatever.app']
答案 1 :(得分:2)
Elementtree需要名称空间URI,而不是名称空间前缀。
var manifestTxt = fs.readFileSync('AndroidManifest.xml', 'utf-8'),
manifestDoc = new et.ElementTree(et.XML(manifestTxt)),
expected = '//application/activity[@{http://schemas.android.com/apk/res/android}name="com.whatever.app"]';
test.ok( manifestDoc.find(expected) );
请参阅:ElementTree: Working with Qualified Names
修改 node-elementtree的XPath实现currently似乎根本没有名称空间支持。
想念你必须做一些腿部工作:
var manifestTxt = fs.readFileSync('AndroidManifest.xml', 'utf-8'),
manifestDoc = new et.ElementTree(et.XML(manifestTxt)),
activities = manifestDoc.findall('//application/activity'), i;
for (i=0; i<activities.length; i++) {
if ( activities[i].attrib['android:name'] === 'com.whatever.app' ) {
test.ok(true);
}
}
if ( activities[i].attrib['android:name'] === 'com.whatever.app' ) {
行很大程度上是猜测。
我不知道解析器如何处理命名空间属性。如果有疑问,只需将整个activities[i].attrib
转储到控制台,看看解析器做了什么。相应地调整上面的代码。我担心你会得到那种有限的XPath支持。