Working with Data from a Specific Document

Previous queries have executed against all the documents in a container, but there are cases where access to data in a single document is the goal. It is possible to isolate a single document component based on the name we assigned to it, and then perform XQuery expressions against it alone.

For example, to select the number attribute from a document named component1 in the components.dbxml container:

dbxml> query '
doc("components.dbxml/component1")/component/@number'

Query      - Starting query execution
Query      - components.dbxml - D('component1',U) : [1] 2 
Query      - components.dbxml - U : [2] 2 3 
Query      - components.dbxml - D('component1',U) : [1] 2 
Query      - Finished query execution, time taken = 3.574ms
1 objects returned for eager expression '
doc("components.dbxml/component1")/component/@number'



dbxml> print
{}number="1" 

Note

The doc function shown here can be used to access XML data external to any BDB XML managed container. For instance, to integrate with a web service that returns XML over HTTP use the doc function to execute that web service and then use the resulting data as part of an XQuery query.

A web service that is able to look up the price of a particular part could be knit into a HTML page as it's built in a single XQuery FLWOR . We have such a simulated service set up to support this example. There is an XML file provided by a web server at oracle.com. It is possible to access that pricing data using the doc function in an XQuery. The URL for the prices file is /intro_xml/prices.xml. The content of that file will provide the prices of the parts that make up our components.

The contents of /intro_xml/prices.xml. looks something like this:

<prices>
    <part number="87">29.95</part>
    <part number="89">19.95</part>
    <part number="150">24.95</part>
    <part number="189">5.00</part>
    <part number="899">9.95</part>
    <part number="901">15.00</part>
</prices>

With that done, we can enhance our earlier parts query to add prices for all the parts. At the same time we'll also convert it to use an HTML table to display the data.

dbxml> query '<html><body>
  <ul>
    {
      for $component in collection("dbxml:components.dbxml")/component
      return 
        <li>
          <b>Component number: {$component/@number/string()}</b><br/>
          <table>
          {
            for $part-ref in $component/uses-part
            return                    
              for $part in collection("dbxml:parts.dbxml")/part[@number = 
                    $part-ref cast as xs:decimal]
                return                            
                <tr><td>{$part/description/string()}</td>
                <td>{
                  doc("/intro_xml/prices.xml")//part[
                        @number = $part/@number]/string()                            
                }</td></tr> 
         }                
         </table>
      </li>
    }
  </ul>
</body></html>'

Query      - Starting query execution
Query      - components.dbxml - U : [2] 2 3 
Query      - parts.dbxml - V(@number,=,'89') : [1] 91 
Query      - parts.dbxml - V(@number,=,'150') : [1] 152 
Query      - parts.dbxml - V(@number,=,'899') : [1] 901 
Query      - parts.dbxml - V(@number,=,'901') : [1] 903 
Query      - parts.dbxml - V(@number,=,'87') : [1] 89 
Query      - parts.dbxml - V(@number,=,'189') : [1] 191 
Query      - Finished query execution, time taken = 2098.29ms
1 objects returned for eager expression '<html><body>
  <ul>
    {
      for $component in collection("dbxml:components.dbxml")/component
      return 
        <li>
          <b>Component number: {$component/@number/string()}</b><br/>
          <table>
          {
            for $part-ref in $component/uses-part
            return                    
              for $part in collection("dbxml:parts.dbxml")/part[@number = 
                    $part-ref cast as xs:decimal]
                return                            
                <tr><td>{$part/description/string()}</td>
                <td>{
                  doc("/intro_xml/prices.xml")//part[
                        @number = $part/@number]/string()                            
                }</td></tr> 
         }                
         </table>
      </li>
    }
  </ul>
</body></html>'

And the result with formatting for readability:

dbxml> print
<html>
    <body>
        <ul>
            <li>
                <b>Component number: 1</b>
                <br/>
                <table>
                    <tr>
                        <td>Description of 89</td>
                        <td>19.95</td>
                    </tr>
                    <tr>
                        <td>Description of 150</td>
                        <td>24.95</td>
                    </tr>
                    <tr>
                        <td>Description of 899</td>
                        <td>9.95</td>
                    </tr>
                </table>
            </li>
            <li>
                <b>Component number: 2</b>
                <br/>
                <table>
                    <tr>
                        <td>Description of 901</td>
                        <td>15.00</td>
                    </tr>
                    <tr>
                        <td>Description of 87</td>
                        <td>29.95</td>
                    </tr>
                    <tr>
                        <td>Description of 189</td>
                        <td>5.00</td>
                    </tr>
                </table>
            </li>
        </ul>
    </body>
</html>

The following shows the previous HTML as displayed in a web browser:

This ability to bring in data from outside BDB XML as part of any query from a web service or other source of XML data provides tremendous power and flexibility when building applications.