xmlstarlet XPath表达式选择单个结果而不是多个
xmlstarlet XPath expression selects single result rather than multiple
我有一个 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,没有给出我预期的结果(在我的系统上,但它给了回答我问题的人)在下面 link
如 link 中所述,我想根据 sid 标签的值查找角色标签名称属性。例如:如果我搜索 abc,查询必须 return Employees, test1, test2 and test3.
这是我使用的脚本:
xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml
但它只给了我 'Employees'。
我正在使用 LINUX /bash。请告诉我,我在 XPATH 表达式中缺少什么。
如果您未绑定到 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>
简而言之,您可以通过使用 ../@*
来解决父子属性。
您使用的 XPath 和 xmlstarlet 命令,
xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml
已经导致返回以下字符串,
Employees
test1
test2
test3
根据要求。
您的 XPath 是正确的;您的 xmlstarlet 命令行是正确的。重新检查您正在使用的文件名以及您 运行 xmlstarlet 所在的目录。重新检查您如何在实际上下文中使用 xmlstarlet 命令的结果。在您 post 编辑的这种简化形式中,预期结果正是返回的结果。
更新:很抱歉听到您仍然卡住了。我的最后一个想法是 post 一份详细的抄本,以证明这应该有效,这样您就可以追溯您的步骤并尝试查看您的路径可能在哪里不同:
c:\gd\usr\kjh\proj\try\xml
> 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:\gd\usr\kjh\proj\try\xml
> xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml
Employees
test1
test2
test3
c:\gd\usr\kjh\proj\try\xml
> xmlstarlet --version
1.5.0
compiled against libxml2 2.9.1, linked with 20901
compiled against libxslt 1.1.28, linked with 10128
c:\gd\usr\kjh\proj\try\xml
> 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:\gd\usr\kjh\proj\try\xml
>
最终更新:
OP 注意到他的 xmlstarlet (v1.0.1) 版本比我在上面的记录中使用的版本 (xmlstarlet v1.5.0) 要老得多。 升级到最新版本的 xmlstarlet 解决了问题。
我有一个 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,没有给出我预期的结果(在我的系统上,但它给了回答我问题的人)在下面 link
如 link 中所述,我想根据 sid 标签的值查找角色标签名称属性。例如:如果我搜索 abc,查询必须 return Employees, test1, test2 and test3.
这是我使用的脚本:
xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml
但它只给了我 'Employees'。
我正在使用 LINUX /bash。请告诉我,我在 XPATH 表达式中缺少什么。
如果您未绑定到 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>
简而言之,您可以通过使用 ../@*
来解决父子属性。
您使用的 XPath 和 xmlstarlet 命令,
xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml
已经导致返回以下字符串,
Employees
test1
test2
test3
根据要求。
您的 XPath 是正确的;您的 xmlstarlet 命令行是正确的。重新检查您正在使用的文件名以及您 运行 xmlstarlet 所在的目录。重新检查您如何在实际上下文中使用 xmlstarlet 命令的结果。在您 post 编辑的这种简化形式中,预期结果正是返回的结果。
更新:很抱歉听到您仍然卡住了。我的最后一个想法是 post 一份详细的抄本,以证明这应该有效,这样您就可以追溯您的步骤并尝试查看您的路径可能在哪里不同:
c:\gd\usr\kjh\proj\try\xml
> 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:\gd\usr\kjh\proj\try\xml
> xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml
Employees
test1
test2
test3
c:\gd\usr\kjh\proj\try\xml
> xmlstarlet --version
1.5.0
compiled against libxml2 2.9.1, linked with 20901
compiled against libxslt 1.1.28, linked with 10128
c:\gd\usr\kjh\proj\try\xml
> 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:\gd\usr\kjh\proj\try\xml
>
最终更新:
OP 注意到他的 xmlstarlet (v1.0.1) 版本比我在上面的记录中使用的版本 (xmlstarlet v1.5.0) 要老得多。 升级到最新版本的 xmlstarlet 解决了问题。