8000 Add namespace usage instructions, add example by vartanbeno · Pull Request #106 · Paligo/xee · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add namespace usage instructions, add example #106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions xee-xpath/examples/namespaces-and-functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use xee_xpath::context::StaticContextBuilder;
use xee_xpath::{DocumentHandle, Documents, Queries, Query};

/// A higher-level wrapper around Xee's XPath functionality
struct Document<'a> {
documents: Documents,
queries: Queries<'a>,
doc_handle: DocumentHandle,
}

impl<'a> Document<'a> {
/// Create a new document with XML content and namespace mappings
fn new(xml: &str, namespaces: &[(&'a str, &'a str)]) -> Self {
let mut documents = Documents::new();
let doc_handle = documents.add_string_without_uri(xml).unwrap();

let mut builder = StaticContextBuilder::default();
for (prefix, uri) in namespaces {
builder.add_namespace(prefix, uri);
}

let queries = Queries::new(builder);
Self {
documents,
queries,
doc_handle,
}
}

/// Execute an XPath query and return the result as a string
fn query(&mut self, xpath: &str) -> String {
self.queries
.sequence(xpath)
.and_then(|it| it.execute(&mut self.documents, self.doc_handle))
.unwrap()
.string_value(self.documents.xot())
.unwrap()
}
}

fn main() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<grocery-list xmlns:item="http://example.com/item"
xmlns:store="http://example.com/store">
<item:description>Weekly grocery shopping list</item:description>
<item:category name="produce" store:section="A1">
<item:product id="p1" organic="true" quantity="6">
<item:name>Banana</item:name>
<item:price currency="USD">0.25</item:price>
<item:unit>each</item:unit>
<store:availability>In stock</store:availability>
</item:product>
<item:product id="p2" organic="false" quantity="1">
<item:name>Lettuce</item:name>
<item:price currency="USD">1.99</item:price>
<item:unit>head</item:unit>
<store:availability>Limited</store:availability>
</item:product>
</item:category>

<item:category name="dairy" store:section="B3">
<item:product id="d1" organic="true" quantity="1">
<item:name>Milk</item:name>
<item:price currency="USD">3.49</item:price>
<item:unit>gallon</item:unit>
<store:availability>In stock</store:availability>
</item:product>
<item:product id="d2" organic="false" quantity="2">
<item:name>Cheese</item:name>
<item:price currency="USD">2.99</item:price>
<item:unit>package</item:unit>
<store:availability>In stock</store:availability>
</item:product>
</item:category>

<item:category name="pantry" store:section="C2">
<item:product id="pn1" organic="false" quantity="1">
<item:name>Pasta</item:name>
<item:price currency="USD">1.49</item:price>
<item:unit>box</item:unit>
<store:availability>In stock</store:availability>
</item:product>
<item:product id="pn2" organic="false" quantity="2">
<item:name>Canned Tomatoes</item:name>
<item:price currency="USD">0.99</item:price>
<item:unit>can</item:unit>
<store:availability>Out of stock</store:availability>
</item:product>
</item:category>
</grocery-list>"#;

let namespaces = [
("item", "http://example.com/item"),
("store", "http://example.com/store"),
];
let mut document = Document::new(xml, &namespaces);

// Get the list description
let description = document.query("/grocery-list/item:description");
println!("List description: {description}");

// Get all products
let products =
document.query("string-join(/grocery-list/item:category/item:product/item:name, ', ')");
println!("Products: {products}");

// Find organic products
let organic_products =
document.query("string-join(//item:product[@organic='true']/item:name, ', ')");
println!("Organic products: {organic_products}");

// Count products in a category
let count = document.query("count(//item:category[@name='produce']/item:product)");
println!("Number of produce items: {count}");

// Calculate total cost of available items only
let total_cost = document.query(
"sum(for $p in //item:product[store:availability='In stock'] return number($p/item:price) * number($p/@quantity))"
);
println!("Total cost of in-stock items: {total_cost}");

// Calculate average price per product
let avg_price =
document.query("round-half-to-even(avg(//item:product/item:price/number()), 2)");
println!("Average price per product: ${avg_price}");
}
24 changes: 23 additions & 1 deletion xee/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,29 @@ If you don't include the file, the XML is taken from stdin, allowing you to do:
cat foo.xml | xee xpath /doc/p
```

#### Working with namespaces

For XML with namespaces, use the `--namespace` option (format: `prefix=uri`):

```
xee xpath /doc/a:p --namespace a=http://example.com foo.xml
```

For multiple namespaces, repeat the option:

```
xee xpath /x:doc/a:p \
--namespace x=http://example.com/x \
--namespace a=http://example.com/a \
foo.xml
```

For XML with a default namespace, use `--default-namespace-uri`:

```
xee xpath /doc/p --default-namespace-uri http://example.com foo.xml
```

### Interactive shell for XPath

Interactive shell (REPL) to issue multiple xpath expressions against a document:
Expand Down Expand Up @@ -83,4 +106,3 @@ a high level API to issue XPath 3.1 expressions in Rust.

This project was made possible by the generous support of
[Paligo](https://paligo.net/).

Loading
0