Wrapper pour les strings Xerces

Depuis peu, j'utilise la librarie XML Xerces d'Apache (pour le moment j'ai touché uniquement au DOM) et cette dernière est extrêmement puissante :
- Rapide,
- API claire,
- Support des XPath,
- API assez proche du c# (Node, Element, même noms de méthodes),
- Multiplateforme,
- Validation des XSD,
- etc.

Comme j'ai pu déjà vous en parler dans un précédent post, je ne trouve pas ce type d'API très sexy car le code produit pour accéder au document XML est assez verbeux et cela est induit par la notion Node/Element/Attribute connue par les utilisateurs de C#.

Dans le cas d'un outil cela ne me gène pas beaucoup mais ce qui me chagrine plus dans le cas de Xerces est la manipulation de strings. En effet, mes premières lignes de code utilisant la librairie Xerces ressemblaient à cela :
XMLCh tempStr[100];
XMLString::transcode("Range", tempStr, 99);
XMLCh const * const pRangeValue =
pMyElem->getAttribute(tempStr);
char const * const pValue = XMLString::transcode(pRangeValue
);
// Do things
XMLString::release(&pValue);

Vous pouvez donc remarquer que la quantité code à produire pour récupérer la valeur d'un attribut est trop importante et rend le tout peu lisible. C'est pourquoi j'ai mis en place une classe pour gérer automatiquement la durée de vie et le buffer de travail des chaînes de caractères pour Xerces :

template <unsigned int Size>
class CXercesString
{
public :

    CXercesString (void);

    ~CXercesString (void);

    CXercesString (char const * const pSrc);

    CXercesString (XMLCh const * const pSrc);

    CXercesString (CXercesString<Size> const & SrcStr);

    CXercesString & operator = (char const * const pSrc);

    CXercesString & operator = (XMLCh    const * const pSrc);

    CXercesString & operator = (CXercesString<Size> const & SrcStr);

    char const * const GetCharArray(void) const;

    XMLCh    const * const GetXMLCh (void) const;

    size_t    GetLength (void) const;

    void    Clear (void);

protected :

    char *         m_pCharArray;
    XMLCh        m_pXercesStr[Size];
};

template <unsigned int Size>
CXercesString<Size> :: CXercesString (void) :
    m_pCharArray(NULL)
{
    memset(m_pXercesStr, 0, sizeof(XMLCh) * Size);
}

template <unsigned int Size>
CXercesString<Size> :: ~CXercesString (void)
{
    if (m_pCharArray)
    {
        XMLString::release(&m_pCharArray);
    }
}

template <unsigned int Size>
CXercesString<Size> :: CXercesString (char const * const pSrc)
{
    assert(pSrc);
    assert(Size > strlen(pSrc));

    XMLString::transcode(pSrc, m_pXercesStr, Size - 1);
    m_pCharArray = XMLString::transcode(m_pXercesStr);
}

template <unsigned int Size>
CXercesString<Size> :: CXercesString (XMLCh const * const pSrc)
{
    assert(pSrc);

    m_pCharArray = XMLString::transcode(pSrc);

    assert(Size > strlen(m_pCharArray));

    XMLString::transcode(m_pCharArray, m_pXercesStr, Size - 1);
}

template <unsigned int Size>
CXercesString<Size> :: CXercesString (CXercesString<Size> const & SrcStr) :
    m_pCharArray(SrcStr.m_pCharArray)
{
    if (m_pCharArray)
    {
        XMLString::transcode(m_pCharArray, m_pXercesStr, Size - 1);
    }
    else
    {
        memset(m_pXercesStr, 0, Size * sizeof(XMLCh));
    }
}

template <unsigned int Size>
CXercesString<Size> & CXercesString<Size> :: operator = (char const * const pSrc)
{
    assert(pSrc);

    Clear();

    m_pCharArray = pSrc;

    if (m_pCharArray)
    {
        XMLString::transcode(m_pCharArray, m_pXercesStr, Size - 1);
    }
    else
    {
        memset(m_pXercesStr, 0, Size * sizeof(XMLCh));
    }

    return (*this);
}

template <unsigned int Size>
CXercesString<Size> & CXercesString<Size> :: operator = (XMLCh    const * const pSrc)
{
    assert(pSrc);

    Clear();

    m_pCharArray = XMLString::transcode(pSrc);

    assert(Size > strlen(m_pCharArray));

    XMLString::transcode(m_pCharArray, m_pXercesStr, Size - 1);

    return (*this);
}

template <unsigned int Size>
CXercesString<Size> & CXercesString<Size> :: operator = (CXercesString<Size> const & SrcStr)
{
    this->operator = (SrcStr.m_pCharArray);

    return (*this);
}

template <unsigned int Size>
char const * const CXercesString<Size> :: GetCharArray(void) const
{
    return (m_pCharArray);
}

template <unsigned int Size>
XMLCh    const * const CXercesString<Size> :: GetXMLCh (void) const
{
    return (&(m_pXercesStr[0]));
}

template <unsigned int Size>
size_t    CXercesString<Size> :: GetLength (void) const
{
    size_t StrSize = 0;

    if (m_pCharArray)
    {
        StrSize = strlen(m_pCharArray);
    }

    return (StrSize);
}

template <unsigned int Size>
void    CXercesString<Size> :: Clear (void)
{
    if (m_pCharArray)
    {
        XMLString::release(&m_pCharArray);
    }

    m_pCharArray = NULL;
    memset(m_pXercesStr, 0, Size * sizeof(XMLCh));
}

Le code précédent devient donc :

{

CXercesString<50> const RangeValue(pMyElem->getAttribute(CXercesString<10>("Range").GetXMLCh()));
}

J'ai codé la classe CXercesString assez rapidement donc, il doit y avoir quelques bugs et il est sûrement possible d'être plus performant ou de fournir une meilleure interface (cast, etc.) mais bon ... l'idée principale est là :)





Article ajouté le 2008-09-21 , consulté 4 fois

Commentaires



Poster un commentaire





http://





Merci de recopier le nombre présent à gauche dans la case de texte ci-dessous ( Pourquoi ? )





Liens

Voir les articles de la catégorie " Programmation "

Retour aux articles



Recommander ce blog | Contacter l'auteur | Reporter un abus | S'abonner au blog Flux RSS du blog | Espace de gestion

Créer un blog gratuit avec Blog4ever