2

I have an XML file having structure like this:

<?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>

Previously, I didn't gave the whole structure in question and the xpath i got in solution, didn't gave the result what I expected (on my system, but it gave to the person who answered my question) in following link search tag attribute value based on child node value using XmlStarlet

AS mentioned in that link, I want to find role tag name attribute based on value of sid tag. for eg: if I search for abc, the query must return Employees, test1, test2 and test3.

Here's the script I used:

xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml

but it gave me only 'Employees'.

I am using LINUX /bash. Please tell me, what I am missing in XPATH expression.

Community
  • 1
  • 1

2 Answers2

1

The XPath and xmlstarlet command you use,

xmlstarlet sel -t -v "//role[.//sid = 'abc']/@name" test.xml

already results in the following strings being returned,

Employees
test1
test2
test3

as requested.

Your XPath is correct; your xmlstarlet command line is correct. Recheck the filename you're using and the directory from which you're running the xmlstarlet. Recheck how you're using the results of the xmlstarlet command in your actual context. In this simplified form you've posted, the expected results are precisely what's being returned.


Update: Sorry to hear you're still stuck. The last idea I have is to post a detailed transcript to provide proof that this should be working so that you can retrace your steps and try to see where your path may be different:

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
>

Final update:

OP noticed that his version of xmlstarlet (v1.0.1) was considerably older than the one I used in the above transcript (xmlstarlet v1.5.0). Upgrading to the latest version of xmlstarlet resolved the problem.

kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • hi @kjhughes, I have my script and my test.xml file in same folder. and i am running the script from that location itself by changing my PWD (present working directory). I am afraid, But still the answer i am getting at command promt is 'employees' and not tes1 test2 – srikanth jagdhane Oct 12 '15 at 12:09
  • Thank you for the detail transcript @kjhuges. My confusion has been removed in one sense. My system is running 1.0.1 version of xmlstarlet. Do you think , its the main reason why i am not going the expected output? – srikanth jagdhane Oct 12 '15 at 14:00
  • I'd upgrade, and if that's not feasible, scour the update logs to see if anything relevant has changed. Good luck. – kjhughes Oct 12 '15 at 14:32
  • 1
    hey @kjhuges, I upgraded the version and guess what, it WORKED!! am so happy. Thanks for your input. :) – srikanth jagdhane Oct 12 '15 at 14:54
  • 1
    Basically the same problem as http://stackoverflow.com/questions/6390807/why-doesnt-xmlstarlet-select-all-nodes, later xmlstarlet versions do the equivalent of `-m XPATH -v . n` automatically. – npostavs Oct 12 '15 at 16:28
0

if you are not bound to xmlstarlet try to use xmllint otherwise adjustment of the xpath like shown below could help.

$ xmllint --xpath '//role//sid/../../@name' roles.xml
 name="Employees" name="Others"

The xml file for this example looked like

<?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>

In short you can address parent childs attribute by addressing them with ../@*.

Marc Bredt
  • 905
  • 5
  • 13
  • hi @emil, Thanks for the answer. Sorry to say that, but i have to develop a script using xmlstarlet only. Anyways, I would surely try your answer too for self development. – srikanth jagdhane Oct 12 '15 at 12:03