我有一个XML文件,它的结构是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<hudson>
<authorizationStrategy>
<roleMap type="globalRoles">
<role name="Employees">
<assignedSIDs>
<sid>abc</sid>
<sid>bcd</sid>
</assignedSIDs>
</role>
</roleMap>
<roleMap type="projectRoles">
<role name="test1" pattern=".*">
<assignedSIDs>
<sid>abc</sid>
<sid>zxc</sid>
</assignedSIDs>
</role>
<role name="test2" pattern=".*">
<permissions/>
<assignedSIDs>
<sid>abc</sid>
<sid>ghi</sid>
</assignedSIDs>
</role>
<role name="test3" pattern=".*">
<permissions/>
<assignedSIDs>
<sid>abc</sid>
</assignedSIDs>
</role>
</roleMap>
</authorizationStrategy>
</hudson>
以前,我没有给出问题中的整个结构和我在解决方案中得到的xpath,没有给出我期望的结果(在我的系统上,但它给了回答我问题的人)使用XmlStarlet
基于子节点值的链接搜索标记属性值正如在该链接中提到的,我想根据sid标签的值找到角色标签名称属性。例如:如果我搜索abc,查询必须返回Employees, test1, test2和test3。
下面是我使用的脚本:xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml
但是它只给了我"雇员"。
我正在使用LINUX/bash。请告诉我,我在XPATH表达式中缺少什么。
您使用的XPath和xmlstarlet命令,
xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml
已经导致返回以下字符串,
Employees
test1
test2
test3
要求。
XPath是正确的;xmlstarlet命令行是正确的。重新检查正在使用的文件名和运行xmlstarlet的目录。重新检查如何在实际上下文中使用xmlstarlet命令的结果。在您发布的这个简化表单中,所返回的正是预期的结果。
更新:很抱歉听到你仍然卡住了。我的最后一个想法是发布一份详细的记录,以证明这应该是有效的,这样你就可以追溯你的步骤,并尝试看看你的路径可能不同:
c:gdusrkjhprojtryxml
> cat test.xml
<?xml version="1.0" encoding="UTF-8"?>
<hudson>
<authorizationStrategy>
<roleMap type="globalRoles">
<role name="Employees">
<assignedSIDs>
<sid>abc</sid>
<sid>bcd</sid>
</assignedSIDs>
</role>
</roleMap>
<roleMap type="projectRoles">
<role name="test1" pattern=".*">
<assignedSIDs>
<sid>abc</sid>
<sid>zxc</sid>
</assignedSIDs>
</role>
<role name="test2" pattern=".*">
<permissions/>
<assignedSIDs>
<sid>abc</sid>
<sid>ghi</sid>
</assignedSIDs>
</role>
<role name="test3" pattern=".*">
<permissions/>
<assignedSIDs>
<sid>abc</sid>
</assignedSIDs>
</role>
</roleMap>
</authorizationStrategy>
</hudson>
c:gdusrkjhprojtryxml
> xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml
Employees
test1
test2
test3
c:gdusrkjhprojtryxml
> xmlstarlet --version
1.5.0
compiled against libxml2 2.9.1, linked with 20901
compiled against libxslt 1.1.28, linked with 10128
c:gdusrkjhprojtryxml
> systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
OS Name: Microsoft Windows 7 Professional
OS Version: 6.1.7601 Service Pack 1 Build 7601
c:gdusrkjhprojtryxml
>
最终更新:
OP注意到他的xmlstarlet版本(v1.0.1)比我在上面的脚本中使用的版本(xmlstarlet v1.5.0)要老得多。升级到最新版本的xmlstarlet解决了这个问题。
如果您没有绑定到xmlstarlet,请尝试使用xmllint,否则像下面所示的那样调整xpath可能会有所帮助。
$ xmllint --xpath '//role//sid/../../@name' roles.xml
name="Employees" name="Others"
这个例子的xml文件看起来像
<?xml version="1.0" ?>
<hudson>
<authorizationStrategy>
<roleMap>
<role name="Employees">
<assignedSIDs>
<sid>abc</sid>
<sid>bcd</sid>
</assignedSIDs>
</role>
<role name="Others">
<assignedSIDs>
<sid>abc</sid>
<sid>zxc</sid>
</assignedSIDs>
</role>
</roleMap>
</authorizationStrategy>
</hudson>
简而言之,您可以通过使用../@*
来寻址父/子属性。