saml-mdq 0.1.0

A Rust client for the SAML Metadata Query (MDQ) Protocol (IETF draft-young-md-query-saml)
# Notes

quick-xml drops namespace prefixes when deserializing with serde, so a prefixed and an unprefixed attribute that share a local name collapse into one serde field. The clearest real-world example comes from SAML metadata in federations like InCommon, which puts both a standard and a namespaced attribute on `<ContactPerson>`:

```xml
<ContactPerson contactType="technical" remd:contactType="http://refeds.org/metadata/contactType/security">
```

Both `contactType` and `remd:contactType` are stripped to the serde field name `@contactType`, producing a `duplicate field` error.

samael worked around this in 0.0.20, which this crate now uses. It replaces the derived `Deserialize` for `ContactPerson` with a hand-written impl. The visitor keeps the first value for a repeated key and skips the rest instead of erroring, and `#[serde(default)]` lets a missing `contact_person` parse. This only patches `ContactPerson`; the underlying quick-xml behavior is unresolved and affects any prefixed attribute.

## Why quick-xml strips namespace prefixes

This is a deliberate pragmatic choice, introduced by Mingun in [PR #490](https://github.com/tafia/quick-xml/pull/490) (Oct 2022) as part of a major serde rewrite. The reasoning, stated explicitly in [issue #757](https://github.com/tafia/quick-xml/issues/757):

> "namespace prefixes does not considered as part of field name because there can be different prefixes for the one namespace even in the same document."

Since the same namespace URI can be bound to different prefixes in different parts of a document (e.g., `xmlns:foo="urn:example"` in one element, `xmlns:bar="urn:example"` in another), matching on prefixes in serde struct field names would break whenever the producer chose a different prefix. Local names are the "stable" part, so `local_name()` was used as a simplification.

However, this is wrong per the [W3C Namespaces in XML spec (Section 6.2)](https://www.w3.org/TR/xml-names/#defaulting): unprefixed attributes are not in any namespace, prefixed attributes are in the namespace bound to that prefix, and they are distinct attributes. For example, `<good a="1" n1:a="2" />` is legal because `a` (no namespace) and `n1:a` (in `n1`'s namespace) have different expanded names. Stripping the prefix makes two spec-distinct attributes appear identical, which is exactly the `contactType` vs `remd:contactType` problem.

This is tracked across several open quick-xml issues:

- [#218 "Struct namespaces with Serde"](https://github.com/tafia/quick-xml/issues/218): master tracking issue, open since 2020
- [#347 "Inconsistent namespace stripping with serde"](https://github.com/tafia/quick-xml/issues/347): labeled `bug`, still open
- [#757 "duplicate field `@type`"](https://github.com/tafia/quick-xml/issues/757): the exact same class of bug with `type` vs `xsi:type`

Partial fixes have been merged incrementally: `xmlns:` prefixes preserved in [PR #539](https://github.com/tafia/quick-xml/pull/539), `xml:` prefixes preserved in [PR #873](https://github.com/tafia/quick-xml/pull/873). But all other namespace prefixes are still stripped.

A proper fix requires namespace-aware serde, which is architecturally hard since serde's data model has no concept of XML namespaces. There's an active WIP by jespersm using James Clark notation (encoding full namespace URIs into serde rename strings like `@{urn:example}contactType`), but it's not ready for PR yet. A narrower interim alternative is to preserve all prefixes, following the pattern of PRs [#539](https://github.com/tafia/quick-xml/pull/539) and [#873](https://github.com/tafia/quick-xml/pull/873).

## Next steps

- Comment on [quick-xml #218](https://github.com/tafia/quick-xml/issues/218) or [#757](https://github.com/tafia/quick-xml/issues/757) linking this use case as another example of real-world breakage
- Attempt an interim PR on quick-xml to preserve all prefixes (not just `xmlns:` and `xml:`), following the pattern of PRs [#539](https://github.com/tafia/quick-xml/pull/539)/[#873](https://github.com/tafia/quick-xml/pull/873)