# Advanced Topics

## Adding new XML parser

Implementing support for the new XML parser requires creating new specializations for `svgpp::policy::xml::attribute_iterator` and `svgpp::policy::xml::element_iterator` class templates using one of existing implementations in folder `include/svgpp/policy/xml` as a sample.

Understanding following types may cause some difficulties:

    template<>
    struct attribute_iterator<CustomXMLAttribute>
    {
      typedef /* ... */ string_type;
      typedef /* ... */ attribute_name_type;
      typedef /* ... */ attribute_value_type;
      typedef /* ... */ saved_value_type;

      /* ... */
    };

`string_type`

  A model of Forward Range, with items of some character type (`char`, `wchar_t`, `char16_t`, `char32_t`). Easy solution is to use `boost::iterator_range<CharT const *>`.

`attribute_name_type`

  Copy constructible type, for which exists method `string_type attribute_iterator::get_string_range(attribute_name_type const &)`. Value of `attribute_name_type` is used only before `attribute_iterator` gets incremented and may become invalid after that.

`attribute_value_type`

  Copy constructible type, for which exists method `string_type attribute_iterator::get_string_range(attribute_value_type const &)`. Value of `attribute_value_type` must be accessible independently of `attribute_iterator` state changes.

`saved_value_type`

  Copy constructible type, for which exists method `attribute_value_type attribute_iterator::get_value(saved_value_type const &)`. Object of this type must as efficiently as possible save attribute value that may be not requested. For example XML parser provides access to XML attribute like this:

      class XmlAttribute
      {
      public:
        std::string getValue() const;
      };

  In this case `saved_value_type` may be defined as `XmlAttribute const *`, instead of `std::string`, to avoid expences of creating and coping string that may not be requested later.

## Value Parsers

To choose proper `value_parser` for the attribute, `traits::attribute_type` metafunction should be used:

    template<class Element, class Attribute>
    struct attribute_type
    {
      typedef /*unspecified*/ type;
    };

The returned type can be:

- One of type tags. E.g. width, as many others attributes has <length> type (corresponds to `tag::type::length`):

      BOOST_MPL_ASSERT(( boost::is_same<
        traits::attribute_type<tag::element::rect, tag::attribute::width>::type,
        tag::type::length> ));

- Attribute tag. E.g. viewBox has its own syntax:

      BOOST_MPL_ASSERT(( boost::is_same<
        traits::attribute_type<tag::element::svg, tag::attribute::viewBox>::type,
        tag::attribute::viewBox> ));

- Pair <element tag, attribute tag>. E.g. type attribute may get different values in elements animateTransform, feColorMatrix, feTurbulence etc.:

      BOOST_MPL_ASSERT(( boost::is_same<
        traits::attribute_type<tag::element::animateTransform, tag::attribute::type>::type,
        boost::mpl::pair<tag::element::animateTransform, tag::attribute::type> > ));

Attribute value parsers interface:

    template<class ValueType, class Args..>
    struct value_parser
    {
      template<class AttributeTag, class Context, class AttributeValue, class PropertySource>
      static bool parse(AttributeTag tag, Context & context, AttributeValue const & attribute_value,
                                        PropertySource source);
    };

`AttributeTag tag`

  Is passed to context, isn’t used by `value_parser` itself

`Context & context`

  Reference to the context that will receive parsed value.

`AttributeValue const & attribute_value`

  Attribute string value

`PropertySource source`

  One of two possible types: `tag::source::attribute` or `tag::source::css`, depending on whether value if from SVG attribute or CSS property.