3

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">&#xA; 
        <activity android:label="@string/app_name" android:name="com.whatever.app">&#xA;                
            <intent-filter>&#xA;</intent-filter>
        </activity> 
    </application>
    <uses-sdk android:minSdkVersion="5" />
</manifest>
4

2 に答える 2

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']
于 2012-06-21T04:55:19.600 に答える
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: 修飾名の操作


編集node-elementtreeの XPath 実装は現在、名前空間をまったくサポートしていないようです。

あなたがいくつかのレッグワークをしなければならないことを見逃しています:

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 サポートで得られるのは、これに限りなく近いものです。

于 2012-06-20T21:59:54.240 に答える