VirtualBox

Changeset 28164 in vbox


Ignore:
Timestamp:
Apr 11, 2010 5:55:37 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
59896
Message:

IPRT: attribute namespace support

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/cpp/xml.h

    r28163 r28164  
    467467    xmlNode     *m_plibNode;            // != NULL if this is an element or content node
    468468    xmlAttr     *m_plibAttr;            // != NULL if this is an attribute node
    469     const char  *m_pcszNamespace;
     469    const char  *m_pcszNamespacePrefix; // not always set
     470    const char  *m_pcszNamespaceHref;   // full http:// spec
    470471    const char  *m_pcszName;            // element or attribute name, points either into plibNode or plibAttr;
    471472                                        // NULL if this is a content node
     
    478479    Node(const Node &x);      // no copying
    479480
    480     void buildChildren();
     481    void buildChildren(const ElementNode &elmRoot);
    481482
    482483    /* Obscure class data */
    483484    struct Data;
    484485    Data *m;
     486
     487    friend class AttributeNode;
    485488};
    486489
     
    530533protected:
    531534    // hide the default constructor so people use only our factory methods
    532     ElementNode(Node *pParent, xmlNode *plibNode);
     535    ElementNode(const ElementNode *pelmRoot, Node *pParent, xmlNode *plibNode);
    533536    ElementNode(const ElementNode &x);      // no copying
     537
     538    const ElementNode *m_pelmRoot;
    534539
    535540    friend class Node;
     
    557562protected:
    558563    // hide the default constructor so people use only our factory methods
    559     AttributeNode(Node *pParent, xmlAttr *plibAttr);
     564    AttributeNode(const ElementNode &elmRoot,
     565                  Node *pParent,
     566                  xmlAttr *plibAttr,
     567                  const char **ppcszKey);
    560568    AttributeNode(const AttributeNode &x);      // no copying
     569
     570    iprt::MiniString    m_strKey;
    561571
    562572    friend class Node;
  • trunk/src/VBox/Runtime/r3/xml.cpp

    r28163 r28164  
    445445      m_plibNode(plibNode),
    446446      m_plibAttr(plibAttr),
    447       m_pcszNamespace(NULL),
     447      m_pcszNamespacePrefix(NULL),
     448      m_pcszNamespaceHref(NULL),
    448449      m_pcszName(NULL),
    449450      m(new Data)
     
    456457}
    457458
    458 void Node::buildChildren()       // private
     459void Node::buildChildren(const ElementNode &elmRoot)       // private
    459460{
    460461    // go thru this element's attributes
     
    462463    while (plibAttr)
    463464    {
    464         const char *pcszAttribName = (const char*)plibAttr->name;
    465         boost::shared_ptr<AttributeNode> pNew(new AttributeNode(this, plibAttr));
     465        const char *pcszKey;
     466        boost::shared_ptr<AttributeNode> pNew(new AttributeNode(elmRoot, this, plibAttr, &pcszKey));
    466467        // store
    467         m->attribs[pcszAttribName] = pNew;
     468        m->attribs[pcszKey] = pNew;
    468469
    469470        plibAttr = plibAttr->next;
     
    477478
    478479        if (plibNode->type == XML_ELEMENT_NODE)
    479             pNew = boost::shared_ptr<Node>(new ElementNode(this, plibNode));
     480            pNew = boost::shared_ptr<Node>(new ElementNode(&elmRoot, this, plibNode));
    480481        else if (plibNode->type == XML_TEXT_NODE)
    481482            pNew = boost::shared_ptr<Node>(new ContentNode(this, plibNode));
     
    486487
    487488            // recurse for this child element to get its own children
    488             pNew->buildChildren();
     489            pNew->buildChildren(elmRoot);
    489490        }
    490491
     
    519520        return true;
    520521    // caller wants namespace:
    521     if (!m_pcszNamespace)
     522    if (!m_pcszNamespacePrefix)
    522523        // but node has no namespace:
    523524        return false;
    524     return !strcmp(m_pcszNamespace, pcszNamespace);
     525    return !strcmp(m_pcszNamespacePrefix, pcszNamespace);
    525526}
    526527
     
    629630}
    630631
    631 ElementNode::ElementNode(Node *pParent, xmlNode *plibNode)
     632ElementNode::ElementNode(const ElementNode *pelmRoot,
     633                         Node *pParent,
     634                         xmlNode *plibNode)
    632635    : Node(IsElement,
    633636           pParent,
     
    635638           NULL)
    636639{
     640    if (!(m_pelmRoot = pelmRoot))
     641        // NULL passed, then this is the root element
     642        m_pelmRoot = this;
     643
    637644    m_pcszName = (const char*)plibNode->name;
    638645
    639     if (    plibNode->ns
    640          && plibNode->ns->prefix
    641        )
    642         m_pcszNamespace = (const char*)m_plibNode->ns->prefix;
     646    if (plibNode->ns)
     647    {
     648        m_pcszNamespacePrefix = (const char*)m_plibNode->ns->prefix;
     649        m_pcszNamespaceHref = (const char*)m_plibNode->ns->href;
     650    }
    643651}
    644652
     
    735743
    736744/**
     745 * Looks up the given attribute node in this element's attribute map.
     746 *
     747 * With respect to namespaces, the internal attributes map stores namespace
     748 * prefixes with attribute names only if the attribute uses a non-default
     749 * namespace. As a result, the following rules apply:
     750 *
     751 *  -- To find attributes from a non-default namespace, pcszMatch must not
     752 *     be prefixed with a namespace.
     753 *
     754 *  -- To find attributes from the default namespace (or if the document does
     755 *     not use namespaces), pcszMatch must be prefixed with the namespace
     756 *     prefix and a colon.
     757 *
     758 * For example, if the document uses the "vbox:" namespace by default, you
     759 * must omit "vbox:" from pcszMatch to find such attributes, whether they
     760 * are specifed in the xml or not.
    737761 *
    738762 * @param pcszMatch
     
    754778 * name and returns its value as a string.
    755779 *
    756  * @param pcszMatch name of attribute to find.
     780 * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    757781 * @param ppcsz out: attribute value
    758782 * @return TRUE if attribute was found and str was thus updated.
     
    774798 * name and returns its value as a string.
    775799 *
    776  * @param pcszMatch name of attribute to find.
     800 * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    777801 * @param str out: attribute value; overwritten only if attribute was found
    778802 * @return TRUE if attribute was found and str was thus updated.
     
    796820 * function returns no error.
    797821 *
    798  * @param pcszMatch name of attribute to find.
     822 * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    799823 * @param i out: attribute value; overwritten only if attribute was found
    800824 * @return TRUE if attribute was found and str was thus updated.
     
    817841 * function returns no error.
    818842 *
    819  * @param pcszMatch name of attribute to find.
     843 * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    820844 * @param i out: attribute value; overwritten only if attribute was found
    821845 * @return TRUE if attribute was found and str was thus updated.
     
    838862 * function returns no error.
    839863 *
    840  * @param pcszMatch name of attribute to find.
     864 * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    841865 * @param i out: attribute value
    842866 * @return TRUE if attribute was found and str was thus updated.
     
    859883 * function returns no error.
    860884 *
    861  * @param pcszMatch name of attribute to find.
     885 * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    862886 * @param i out: attribute value; overwritten only if attribute was found
    863887 * @return TRUE if attribute was found and str was thus updated.
     
    879903 * "yes", "no", "1" or "0" as valid values.
    880904 *
    881  * @param pcszMatch name of attribute to find.
     905 * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    882906 * @param f out: attribute value; overwritten only if attribute was found
    883907 * @return TRUE if attribute was found and str was thus updated.
     
    930954
    931955    // now wrap this in C++
    932     ElementNode *p = new ElementNode(this, plibNode);
     956    ElementNode *p = new ElementNode(m_pelmRoot, this, plibNode);
    933957    boost::shared_ptr<ElementNode> pNew(p);
    934958    m->children.push_back(pNew);
     
    9811005        // libxml side: xmlNewProp creates an attribute
    9821006        xmlAttr *plibAttr = xmlNewProp(m_plibNode, (xmlChar*)pcszName, (xmlChar*)pcszValue);
    983         const char *pcszAttribName = (const char*)plibAttr->name;
    9841007
    9851008        // C++ side: create an attribute node around it
    986         boost::shared_ptr<AttributeNode> pNew(new AttributeNode(this, plibAttr));
     1009        const char *pcszKey;
     1010        boost::shared_ptr<AttributeNode> pNew(new AttributeNode(*m_pelmRoot, this, plibAttr, &pcszKey));
    9871011        // store
    988         m->attribs[pcszAttribName] = pNew;
     1012        m->attribs[pcszKey] = pNew;
    9891013    }
    9901014    else
     
    10481072}
    10491073
    1050 AttributeNode::AttributeNode(Node *pParent, xmlAttr *plibAttr)
     1074/**
     1075 * Private constructur for a new attribute node. This one is special:
     1076 * in ppcszKey, it returns a pointer to a string buffer that should be
     1077 * used to index the attribute correctly with namespaces.
     1078 *
     1079 * @param pParent
     1080 * @param elmRoot
     1081 * @param plibAttr
     1082 * @param ppcszKey
     1083 */
     1084AttributeNode::AttributeNode(const ElementNode &elmRoot,
     1085                             Node *pParent,
     1086                             xmlAttr *plibAttr,
     1087                             const char **ppcszKey)
    10511088    : Node(IsAttribute,
    10521089           pParent,
     
    10551092{
    10561093    m_pcszName = (const char*)plibAttr->name;
     1094
     1095    *ppcszKey = m_pcszName;
     1096
     1097    if (    plibAttr->ns
     1098         && plibAttr->ns->prefix
     1099       )
     1100    {
     1101        m_pcszNamespacePrefix = (const char*)plibAttr->ns->prefix;
     1102        m_pcszNamespaceHref = (const char*)plibAttr->ns->href;
     1103
     1104        if (    !elmRoot.m_pcszNamespaceHref
     1105             || (strcmp(m_pcszNamespaceHref, elmRoot.m_pcszNamespaceHref))
     1106           )
     1107        {
     1108            // not default namespace:
     1109            m_strKey = m_pcszNamespacePrefix;
     1110            m_strKey.append(':');
     1111            m_strKey.append(m_pcszName);
     1112
     1113            *ppcszKey = m_strKey.c_str();
     1114        }
     1115    }
    10571116}
    10581117
     
    11911250void Document::refreshInternals() // private
    11921251{
    1193     m->pRootElement = new ElementNode(NULL, xmlDocGetRootElement(m->plibDocument));
    1194 
    1195     m->pRootElement->buildChildren();
     1252    m->pRootElement = new ElementNode(NULL, NULL, xmlDocGetRootElement(m->plibDocument));
     1253
     1254    m->pRootElement->buildChildren(*m->pRootElement);
    11961255}
    11971256
     
    12341293
    12351294    // now wrap this in C++
    1236     m->pRootElement = new ElementNode(NULL, plibRootNode);
     1295    m->pRootElement = new ElementNode(NULL, NULL, plibRootNode);
    12371296
    12381297    return m->pRootElement;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette