如何使用NodeJS根据Text属性获取元素的完整XPath
如何使用NodeJS获取通过Text属性定位的元素的完整XPath?
以下是对应的XML内容:
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> <hierarchy index="0" class="hierarchy" rotation="0" width="1440" height="3036"> <android.widget.FrameLayout index="0" package="com.google.android.permissioncontroller" class="android.widget.FrameLayout" text="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[37,1017][1403,2102]" displayed="true"> <android.widget.FrameLayout index="0" package="com.google.android.permissioncontroller" class="android.widget.FrameLayout" text="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[37,1017][1403,2102]" displayed="true"> <android.widget.FrameLayout index="0" package="com.google.android.permissioncontroller" class="android.widget.FrameLayout" text="" resource-id="android:id/content" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[37,1017][1403,2102]" displayed="true"> <android.widget.ScrollView index="0" package="com.google.android.permissioncontroller" class="android.widget.ScrollView" text="" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[37,1017][1403,2102]" displayed="true"> <android.widget.LinearLayout index="0" package="com.google.android.permissioncontroller" class="android.widget.LinearLayout" text="" resource-id="com.android.permissioncontroller:id/grant_singleton" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[37,1017][1403,2102]" displayed="true"> <android.widget.LinearLayout index="0" package="com.google.android.permissioncontroller" class="android.widget.LinearLayout" text="" resource-id="com.android.permissioncontroller:id/grant_dialog" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[37,1017][1403,2102]" displayed="true"> <android.widget.LinearLayout index="0" package="com.google.android.permissioncontroller" class="android.widget.LinearLayout" text="" resource-id="com.android.permissioncontroller:id/content_container" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[93,1073][1347,1549]" displayed="true"> <android.widget.LinearLayout index="0" package="com.google.android.permissioncontroller" class="android.widget.LinearLayout" text="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[177,1136][1263,1465]" displayed="true"> <android.widget.ImageView index="0" package="com.google.android.permissioncontroller" class="android.widget.ImageView" text="" resource-id="com.android.permissioncontroller:id/permission_icon" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[664,1136][776,1248]" displayed="true" /> <android.widget.TextView index="1" package="com.google.android.permissioncontroller" class="android.widget.TextView" text="Allow App to send you notifications?" resource-id="com.android.permissioncontroller:id/permission_message" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[177,1290][1263,1465]" displayed="true" /> </android.widget.LinearLayout> </android.widget.LinearLayout> <android.widget.LinearLayout index="1" package="com.google.android.permissioncontroller" class="android.widget.LinearLayout" text="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[93,1549][1347,2046]" displayed="true"> <android.widget.Button index="0" package="com.google.android.permissioncontroller" class="android.widget.Button" text="Allow" resource-id="com.android.permissioncontroller:id/permission_allow_button" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[177,1556][1263,1752]" displayed="true" /> <android.widget.Button index="1" package="com.google.android.permissioncontroller" class="android.widget.Button" text="Don’t allow" resource-id="com.android.permissioncontroller:id/permission_deny_button" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[177,1766][1263,1962]" displayed="true" /> </android.widget.LinearLayout> </android.widget.LinearLayout> </android.widget.LinearLayout> </android.widget.ScrollView> </android.widget.FrameLayout> </android.widget.FrameLayout> </android.widget.FrameLayout> </hierarchy>
我需要获取文本为Allow的第一个按钮的完整XPath,预期XPath为:/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.ScrollView/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.LinearLayout[2]/android.widget.Button[1]
实现方案
可以用NodeJS的xmldom和xpath库解析XML并生成目标XPath,步骤如下:
- 安装依赖
执行命令安装所需库:
npm install xmldom xpath
- 编写代码
以下代码会定位到文本为Allow的按钮,并生成完整层级XPath:
const { DOMParser } = require('xmldom'); const xpath = require('xpath'); // 替换为你的XML内容 const xmlContent = `<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> <hierarchy index="0" class="hierarchy" rotation="0" width="1440" height="3036"> <!-- 完整XML内容 --> </hierarchy>`; // 解析XML为DOM对象 const doc = new DOMParser().parseFromString(xmlContent, 'text/xml'); const select = xpath.useNamespaces({}); // 定位目标元素 const targetElement = select("//*[@text='Allow']", doc)[0]; // 生成完整XPath的函数 function generateFullXPath(element) { const path = []; let current = element; while (current && current.nodeType === 1) { let tagName = current.tagName; // 统计同级同标签元素数量,确定索引 const siblings = current.parentNode.childNodes; let sameTagCount = 0; let position = 1; for (const sibling of siblings) { if (sibling.nodeType === 1 && sibling.tagName === tagName) { sameTagCount++; if (sibling === current) position = sameTagCount; } } // 同级同标签超过1个时添加索引 if (sameTagCount > 1) tagName += `[${position}]`; path.unshift(tagName); current = current.parentNode; } return '/' + path.join('/'); } // 输出结果 const fullXPath = generateFullXPath(targetElement); console.log(fullXPath);
- 代码说明
- 用
DOMParser把XML字符串转为DOM对象; - 用XPath表达式
//*[@text='Allow']定位目标按钮; generateFullXPath函数从目标元素向上遍历父节点,统计每个节点在同级同标签中的位置,拼接成完整层级XPath;- 运行代码后输出的XPath与预期完全一致。
内容的提问来源于stack exchange,提问作者Aritra Nayak
相关产品推荐
相关产品推荐

