2012-06-20 1 views
2

Используя пакет elementtree в nodejs, я пытаюсь проверить существование определенного xml-атрибута в XML-файле (в частности, манифест android файл).Поиск выражения xpath с помощью двоеточия в имени атрибута name вызывает (node.js elementtree module)

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> 
+0

Вы пробовали экранировать двоеточие '\:'? – mVChr

+0

Да, никакого эффекта. – wildabeast

ответ

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


Редактировать Реализация XPath из node-elementtree не кажется currently иметь поддержку пространств имен вообще.

Missing, что вы должны сделать некоторые беготней:

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.

+0

Спасибо, я попробовал это, и хотя он больше не выбрасывал исключение, поиск не удался (так что я понял, что это тоже не так). Я добавил образец xml, который я ищу. Итак, тогда возникает вопрос, почему поиск не срабатывает? – wildabeast

+0

Это все, но XPath ... –

+0

@DimitreNovatchev Правильно. В любом случае, так как ElementTree работает в соответствии с документацией (см. Ссылку «Работа с квалифицированными именами» выше). Я ничего не могу поделать. – Tomalak

6

В случае, если у вас нет информации, как зарегистрировать пространство имен и использовать соответствующий префикс для него, используйте:

application/activity 
    [@*[local-name()=name' 
    and 
     namespace-uri() = 'http://schemas.android.com/apk/res/android' 
     ] 
    = 
    'com.whatever.app' 
    ] 

Simpler выражения, которые не являются безопасными в общем случае, но может выбрать желаемое узел (ы) в данном конкретном случае:

application/activity[@*[local-name()='name'] = 'com.whatever.app'] 

или это выражение:

application/activity[@*[name()='android:name'] = 'com.whatever.app']