kozooh
kozooh

Reputation: 2115

How to get an element that is a children of a tag with a specified value in XML?

I am doing a POST in jQuery and as a result I get a response in XML format like that one:

<struct>
    <member>
        <name>ITEMS</name>
        <value>
            <array>
                <data>
                    <value>
                        <struct>
                            <member>
                                <name>item1</name>
                                <value>
                                    <boolean>value1</boolean>
                                </value>
                            </member>
                            <member>
                                <name>item2</name>
                                <value>
                                    <boolean>value2</boolean>
                                </value>
                            </member>
                            <member>
                                <name>item3</name>
                                <value>
                                    <string>value3</string>
                                </value>
                            </member>
                            <member>
                                <name>item4</name>
                                <value>
                                    <string>value4</string>
                                </value>
                            </member>
                        </struct>
                    </value>
                </data>
            </array>
        </value>
    </member>
</struct>

Could you tell me how to extract the boolean value (value1) preceded by item1 and the string value (value3) preceded by item3? I know that I can do find('boolean') and find('string') and then take values I'm interested in but I'm thinking if there's more elegant way to do that (using items between tags <name>).

EDIT: I got another problem since item names are repeating like.

 <struct>
        <member>
            <name>ITEMS</name>
            <value>
                <array>
                    <data>
                        <value>
                            <struct>
                                <member>
                                    <name>item1</name>
                                    <value>
                                        <boolean>value1</boolean>
                                    </value>
                                </member>
                                <member>
                                    <name>item2</name>
                                    <value>
                                        <boolean>value2</boolean>
                                    </value>
                                </member>
                                <member>
                                    <name>item3</name>
                                    <value>
                                        <string>value3</string>
                                    </value>
                                </member>
                                <member>
                                    <name>item4</name>
                                    <value>
                                        <string>value4</string>
                                    </value>
                                </member>
                            </struct>
                            <struct>
                                <member>
                                    <name>item1</name>
                                    <value>
                                        <boolean>value5</boolean>
                                    </value>
                                </member>
                                <member>
                                    <name>item2</name>
                                    <value>
                                        <boolean>value6</boolean>
                                    </value>
                                </member>
                                <member>
                                    <name>item3</name>
                                    <value>
                                        <string>value7</string>
                                    </value>
                                </member>
                                <member>
                                    <name>item4</name>
                                    <value>
                                        <string>value8</string>
                                    </value>
                                </member>
                            </struct>
                        </value>
                    </data>
                </array>
            </value>
        </member>
    </struct>

When I run @Rick Hitchcock find function I get all values sticked together, i.e. find('item1','boolean') returns "value1value2". How can I separate the data to put it into the object like:

var myVector; // vector where I store my objects

myVector[0] = { // object with items from the first <struct> tag
item1: value1,
item2: value2,
item3: value3,
item4: value4
}

myVector[1] = {  // object with items from the second <struct> tag
item1: value5,
item2: value6,
item3: value7,
item4: value8
}

etc...

Upvotes: 0

Views: 29

Answers (2)

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

Use filter() to go directly to a name, then next() and find() to grab the data:

var bool= $('name').filter(function() {
  return $(this).text()=='item1';
}).next().find('boolean').text();

var str= $('name').filter(function() {
  return $(this).text()=='item3';
}).next().find('string').text();

You can make this into a function:

function find(name, type) {
  return $('name').filter(function() {
    return $(this).text()==name;
  }).next().find(type).text();
}

console.log(find('item1', 'boolean'));  //value1
console.log(find('item3', 'string'));   //value3

Based on your updated question, you could use this function:

function find(name, type, vector) {
  $('name')
    .filter(function() {
      return $(this).text()==name;
    })
    .next()
      .find(type).each(function(idx) {
        vector[idx]= vector[idx] || {};
        vector[idx][name]= $(this).text();
      });
}

You would call it like this, passing myVector to the function:

var myVector = [];
find('item1', 'boolean', myVector);
find('item3', 'string', myVector);

function find(name, type, vector) {
  $('name')
    .filter(function() {
      return $(this).text()==name;
    })
    .next()
      .find(type).each(function(idx) {
        vector[idx]= vector[idx] || {};
        vector[idx][name]= $(this).text();
      });
}

var myVector = [];
find('item1', 'boolean', myVector);
find('item3', 'string', myVector);

$('#output').html(JSON.stringify(myVector, null, 2));
struct {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="output"></pre>
<struct>
  <member>
    <name>ITEMS</name>
    <value>
      <array>
        <data>
          <value>
            <struct>
              <member>
                <name>item1</name>
                <value>
                  <boolean>value1</boolean>
                </value>
              </member>
              <member>
                <name>item2</name>
                <value>
                  <boolean>value2</boolean>
                </value>
              </member>
              <member>
                <name>item3</name>
                <value>
                  <string>value3</string>
                </value>
              </member>
              <member>
                <name>item4</name>
                <value>
                  <string>value4</string>
                </value>
              </member>
            </struct>
            <struct>
              <member>
                <name>item1</name>
                <value>
                  <boolean>value5</boolean>
                </value>
              </member>
              <member>
                <name>item2</name>
                <value>
                  <boolean>value6</boolean>
                </value>
              </member>
              <member>
                <name>item3</name>
                <value>
                  <string>value7</string>
                </value>
              </member>
              <member>
                <name>item4</name>
                <value>
                  <string>value8</string>
                </value>
              </member>
            </struct>
          </value>
        </data>
      </array>
    </value>
  </member>
</struct>

Upvotes: 1

Dmytro Pastovenskyi
Dmytro Pastovenskyi

Reputation: 5419

You can apply xPath on this XML.

//member[name='item1']/value/boolean/text() | //member[name='item3']/value/string/text()

Upvotes: 0

Related Questions