I haven't full grokked why this difference is needed, but it would be good to encapsulate it somehow so that the object returned here adheres to a common interface. For example perhaps you could have a "type reference" object, responding to `#type`, which might either be a `NamedTypeReference` or an `ImmediateTypeReference`. Then `Element#type` could just call `@type_reference.type` rather than having to know that `@type` might be a string.

BTW, minor point but I'd probably check `data.respond_to?(:to_str)` rather than `data.is_a?(String)` - it's just a little more flexible.