Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

Substitute.cxx

Go to the documentation of this file.
00001 // $Header: /nfs/slac/g/glast/ground/cvs/xmlUtil/src/Substitute.cxx,v 1.3 2002/04/05 18:25:18 jrb Exp $
00002 
00003 #include <vector>
00004 #include <string>
00005 #include "xmlUtil/Substitute.h"
00006 #include "xml/Dom.h"
00007 #include "xmlUtil/Arith.h"
00008 #include <dom/DOM_Element.hpp>
00009 #include <dom/DOM_TreeWalker.hpp>
00010 #include <dom/DOM_NamedNodeMap.hpp>
00011 #include <vector>
00012 
00013 namespace xmlUtil {
00014 
00015   Substitute::Substitute(DOM_Document doc, std::string suffix) :
00016     m_doc(doc), m_count(0), m_suffix(suffix) {
00017     m_suffixLen = suffix.size();
00018   }
00019 
00020   int Substitute::execute(DOM_Element top) {
00021     // Get rid of some inefficiency by means of the following imperfect
00022     // mechanism:
00023     //   An element may have an attribute called "substituted".  If it
00024     //   does, the attribute always has a default value of "false".
00025     //   The execute method looks for the attribute.  If it is there and
00026     //   has value "true", substitution has already been done, so just
00027     //   return.  If the attribute has value "false" or doesn't exist,
00028     //   go ahead and do the substitution.  Afterwards, if the attribute
00029     //   exists set its value to "true", but don't add any new attributes.
00030     //   Also as a matter of course always check the root element for
00031     //   a "substituted" attribute.
00032     //
00033     //   If an element and its descendent *both* have the substituted
00034     //   attribute, only the one passed to execute will have its substitute
00035     //   attribute examined and possibly changed.  This means it's possible
00036     //   for an element to have a "substituted" attribute value of "false"
00037     //   when it really should be "true", but never the other way around.
00038     //   
00039     DOM_Element docElt = m_doc.getDocumentElement();
00040     if ((docElt.getAttribute("substituted")).equals(DOMString("true"))) 
00041       return 0;
00042     
00043     if ((top.getAttribute("substituted")).equals(DOMString("true"))) return 0;
00044     DOM_Node curNode = top;
00045 
00046     // This is not explained anywhere in the xerces doc. that I
00047     // can see, but from the code in TreeWalkerImpl::acceptNode
00048     // this would seem to be the right value for whatToShow
00049     unsigned long whatToShow = 1 << (DOM_Node::ELEMENT_NODE -1);
00050 
00051     DOM_TreeWalker walker = m_doc.createTreeWalker(top, whatToShow, 0, 0);
00052     m_count = 0;
00053     while (curNode != DOM_Node() ) {
00054       sub(static_cast<DOM_Element &> (curNode));
00055       curNode = walker.nextNode();
00056     }
00057     DOM_Attr subNode = top.getAttributeNode("substituted");
00058     if (subNode != DOM_Attr()) { 
00059       subNode.setValue("true");
00060     }
00061 
00062     return m_count;
00063   }
00064 
00065   void Substitute::sub(DOM_Element elt) {
00066     DOM_NamedNodeMap attMap = elt.getAttributes();
00067     int   nAtt = attMap.getLength();
00068     int   iAtt;
00069     std::vector<DOMString> toProcess;
00070     std::vector<unsigned> toProcessPos;
00071     //    std::vector<DOM_Node> toDelete;
00072 
00073     for (iAtt = 0; iAtt <nAtt; iAtt++) {
00074       DOM_Node att = attMap.item(iAtt);
00075       //      if (att != DOM_Node()) { // probably not necessary
00076       DOMString  attString = att.getNodeName();
00077       std::string attName = std::string(xml::Dom::transToChar(attString));
00078       
00079         // Look for suffix
00080       unsigned pos = attName.find(m_suffix, attName.size() - m_suffixLen);
00081       if  (pos < attName.size())  { // found
00082         toProcess.push_back(attString);
00083         toProcessPos.push_back(pos);
00084       }
00085     }
00086 
00087     // Now process by name
00088     while (toProcess.size() > 0) {
00089       DOMString oldAttString = toProcess.back();
00090       std::string oldAttName = 
00091         std::string(xml::Dom::transToChar(oldAttString));
00092       unsigned  pos = toProcessPos.back();
00093       toProcess.pop_back();
00094       toProcessPos.pop_back();
00095       DOM_Element constElt =
00096         m_doc.getElementById(elt.getAttribute(oldAttString));
00097       if (constElt == DOM_Element() ) { // shouldn't happen
00098         m_notFound++;
00099         continue;
00100       }
00101       // Build the new attribute
00102       DOMString val = constElt.getAttribute(DOMString("value"));
00103 
00104       // If the element referred to is a <prim>, we should be done
00105       // because it always has a value.  If it's a <const>
00106       // we may have to evaluate it.
00107       if (val == DOMString()) { // try evaluating it
00108         Arith curArith(constElt);
00109         double evalValue = curArith.evaluate();
00110         curArith.saveValue();
00111         val = constElt.getAttribute(DOMString("value"));
00112       }
00113 
00114       std::string newAttName = oldAttName.erase(pos, oldAttName.size()  );
00115       elt.setAttribute(DOMString(newAttName.c_str()), val);
00116       elt.removeAttribute(oldAttString);
00117       m_count++;
00118     }
00119 
00120     // Now delete each saved attribute node 
00121     // while (toDelete.size() > 0) {
00122     //      DOM_Node att = toDelete.back();
00123     //      toDelete.pop_back();
00124     //      elt.removeAttributeNode(static_cast <DOM_Attr &>(att));
00125     //    }
00126   }
00127 }

Generated on Wed Oct 16 14:02:48 2002 by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001