Orb/python/orb/guidiser.py
changeset 2 932c358ece3e
child 4 468f4c8d3d5b
equal deleted inserted replaced
1:82f11024044a 2:932c358ece3e
       
     1 # Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved.
       
     2 # This component and the accompanying materials are made available under the terms of the License 
       
     3 # "Eclipse Public License v1.0" which accompanies this distribution, 
       
     4 # and is available at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     5 #
       
     6 # Initial Contributors:
       
     7 # Nokia Corporation - initial contribution.
       
     8 #
       
     9 # Contributors:
       
    10 #
       
    11 # Description:
       
    12 #
       
    13 from __future__ import with_statement
       
    14 import unittest
       
    15 import uuid
       
    16 import os
       
    17 import stat
       
    18 import sys
       
    19 import shutil
       
    20 import xml
       
    21 import logging
       
    22 from optparse import OptionParser, check_choice
       
    23 from xml.etree import ElementTree as etree
       
    24 from cStringIO import StringIO
       
    25 from lib import scan, xml_decl, doctype_identifier, XmlParser
       
    26 from doxyidredirect import DoxyIdRedirect, ExceptionDoxyIdRedirectLookup
       
    27 
       
    28 
       
    29 __version__ = "0.1"
       
    30 
       
    31 class Guidiser(object):
       
    32     """
       
    33     A simple class that parses an xml file and converts the values of all
       
    34     id, href and keyref attributes to a 'GUID'.
       
    35     
       
    36     >>> guid = Guidiser()
       
    37     >>> root = guid.guidise(StringIO(cxxclass))
       
    38     >>> oldroot = etree.parse(StringIO(cxxclass)).getroot()
       
    39     >>> oldroot.attrib['id']
       
    40     'CP_class'
       
    41     >>> root.attrib['id']
       
    42     'GUID-25825EC4-341F-3EA4-94AA-7DCE380E6D2E'
       
    43     """
       
    44     # Publishing targets
       
    45     PT_MODE = 0
       
    46     PT_DITAOT = 1
       
    47     PUBLISHING_TARGETS = (PT_MODE, PT_DITAOT)
       
    48     
       
    49     def __init__(self, namespace='www.nokia.com', publishing_target=0, xmlparser=XmlParser(), doxyidredirect=DoxyIdRedirect(None)):
       
    50         self.namespace = self._get_namespace(namespace)
       
    51         self.set_publishing_target(publishing_target)
       
    52         self.xmlparser = xmlparser
       
    53         self.doxyidredirect = doxyidredirect
       
    54         
       
    55     def set_publishing_target(self, target):
       
    56         if not target in self.PUBLISHING_TARGETS:
       
    57             raise Exception('Invalid Publishing Target \"%s\"' % target)
       
    58         self._publishing_target = target
       
    59         
       
    60     def get_publishing_target(self):
       
    61         return self._publishing_target
       
    62         
       
    63     def _get_namespace(self, namespace, LEN_BYTES=16):
       
    64         if len(namespace) < LEN_BYTES:
       
    65             namespace = namespace + (' ' * (LEN_BYTES - len(namespace)))
       
    66         return uuid.UUID(bytes=namespace[:LEN_BYTES])
       
    67     
       
    68     def _get_guid(self, fqn):
       
    69         return ('GUID-%s' % (uuid.uuid3(self.namespace, fqn))).upper()
       
    70                         
       
    71     def _guidise_href(self, href, tag):
       
    72         if tag == "xref":
       
    73             return self._guidise_xref_href(href)
       
    74         else:
       
    75             # Tag is a topicref or topicref descended element
       
    76             return self._guidise_topicref_href(href)
       
    77     
       
    78     def _guidise_topicref_href(self, href):
       
    79         # Guidise an href that points to a ditamap
       
    80         # NOTE: the id of the map is assumed to be the same as the filename
       
    81         # (minus the ".ditamap" extension)
       
    82         if href.endswith(".ditamap"):
       
    83             guid = self._get_guid(href[:-len(".ditamap")])
       
    84             if self.get_publishing_target() == self.PT_DITAOT:
       
    85                 guid += ".ditamap"
       
    86             return guid
       
    87         
       
    88         # Guidise an href that points to a topic
       
    89         # NOTE: Doxygen currently outputs "filepath#topicid" for topicref hrefs
       
    90         # the "#topicid" is redundant (as topicrefs can't reference below the topic level)
       
    91         # so will probably be removed from doxygen output at some point.
       
    92         filename = href.split('#')[0]
       
    93         id = os.path.splitext(filename)[0]
       
    94         fqn = None
       
    95         if not(id.lower() in ("test", "deprecated", "todo") or id.lower().find("namespace_") != -1):                
       
    96             try:
       
    97                 filename, fqn = self.doxyidredirect.lookupId(id)
       
    98             except ExceptionDoxyIdRedirectLookup, err:
       
    99                 logging.error("Could not lookup Fully Qualified APIName for id '%s' in href '%s'" % (id, href))
       
   100         #if the id was not found just guidise the id
       
   101         #this is just to make the id unique for mode
       
   102         guid = self._get_guid(fqn) if fqn else self._get_guid(id)
       
   103         if self.get_publishing_target() == self.PT_DITAOT:
       
   104             guid+=".xml"
       
   105         return guid
       
   106     
       
   107     def _guidise_xref_href(self, href):
       
   108         # Don't guidise references without hashes. Assume they are filepaths
       
   109         # to files other than ditatopics
       
   110         if href.find('#') == -1:
       
   111             return href
       
   112 			
       
   113         # Doxygen currently outputs hrefs in the format autolink_8cpp.xml#autolink_8cpp_1ae0e289308b6d2cbb5c86e753741981dc
       
   114         # The right side of the # is not enough to extract the fully qualified name of the function because it is md5ed
       
   115         # Send the right side to doxyidredirect to get the fqn of the function			
       
   116         filename, id = href.split('#')
       
   117         fqn = None                
       
   118         if not(id.lower() in ("test", "deprecated", "todo") or id.lower().find("namespace_") != -1):                        
       
   119             try:
       
   120                 fqn = self.doxyidredirect.lookupId(id)[1]
       
   121             except ExceptionDoxyIdRedirectLookup, err:
       
   122                 logging.error("No API name for element id %s, guidising id instead" % id)
       
   123 
       
   124         guid = self._get_guid(fqn) if fqn else self._get_guid(id)
       
   125         basename, ext = os.path.splitext(filename)
       
   126         try:
       
   127             base_guid = self._get_guid(self.doxyidredirect.lookupId(basename)[1])
       
   128         except ExceptionDoxyIdRedirectLookup, e:
       
   129             base_guid = self._get_guid(basename)
       
   130             
       
   131         if self.get_publishing_target() == self.PT_DITAOT:
       
   132             return base_guid + ext + "#" + guid
       
   133         else:
       
   134             return guid
       
   135     
       
   136     def _guidise_id(self, id):
       
   137         try:
       
   138             filename, fqn = self.doxyidredirect.lookupId(id)
       
   139             return self._get_guid(fqn)
       
   140         except ExceptionDoxyIdRedirectLookup, err:
       
   141             logging.debug("Didn't find a Fully Qualified APIName for id '%s'" % id)
       
   142             return self._get_guid(id)
       
   143     
       
   144     def guidise(self, xmlfile):
       
   145         #WORKAROUND: ElementTree provides no function to set prefixes and makes up its own if they are not set (ns0, ns1, ns2)
       
   146         etree._namespace_map["http://dita.oasis-open.org/architecture/2005/"] = 'ditaarch'
       
   147         try:
       
   148             root = etree.parse(xmlfile).getroot()
       
   149         except xml.parsers.expat.ExpatError, e:
       
   150             logging.error("%s could not be parsed: %s\n" % (xmlfile, str(e)))
       
   151             return None
       
   152         for child in root.getiterator():
       
   153             for key in [key for key in ('id', 'href', 'keyref') if key in child.attrib]:
       
   154                 if key == 'id':
       
   155                     child.attrib['id'] = self._guidise_id(child.attrib['id'])
       
   156                 elif key == 'href':
       
   157                     if 'format' in child.attrib and child.attrib['format'] == 'html':
       
   158                         continue
       
   159                     else:
       
   160                         base_dir = os.path.dirname(xmlfile) if isinstance(xmlfile, str) else ""
       
   161                         child.attrib['href'] = self._guidise_href(child.attrib['href'], child.tag)
       
   162                 elif key == 'keyref':
       
   163                     child.attrib['keyref'] = self._get_guid(child.attrib['keyref'])                    
       
   164 
       
   165         return root
       
   166     
       
   167 
       
   168 def updatefiles(xmldir, publishing_target="ditaot"):
       
   169     publishing_target = Guidiser.PT_MODE if (publishing_target == "mode") else Guidiser.PT_DITAOT
       
   170     guidiser = Guidiser(publishing_target=publishing_target, doxyidredirect=DoxyIdRedirect(xmldir))
       
   171     for filepath in scan(xmldir):
       
   172         logging.debug('Guidising file \"%s\"' % filepath)
       
   173         root = guidiser.guidise(filepath)
       
   174         if root is not None:
       
   175             try:
       
   176                 os.chmod(filepath, stat.S_IWRITE)
       
   177             except Exception, e:
       
   178                 logging.error("Could not make file \"%s\" writable, error was \"%s\"" % (filepath, e))
       
   179                 continue            
       
   180             with open(filepath, 'w') as f:
       
   181                 f.write(xml_decl()+'\n')
       
   182                 try:
       
   183                     doc_id = doctype_identifier(root.tag)
       
   184                 except Exception, e:
       
   185                     logging.error("Could not write doctype identifier for file \"%s\", error was \"%s\""
       
   186                                   %(filepath, e))
       
   187                 else:
       
   188                     f.write(doc_id+'\n')
       
   189                 f.write(etree.tostring(root))        
       
   190                 f.close()
       
   191                 
       
   192 def main():
       
   193     usage = "usage: %prog [options] <Path to the XML content>"
       
   194     parser = OptionParser(usage, version='%prog ' + __version__)
       
   195     parser.add_option("-p", dest="publishing_target", type="choice", choices=["mode", "ditaot"], default="mode", 
       
   196                       help="Publishing Target: mode|ditaot, [default: %default]")
       
   197     parser.add_option("-l", "--loglevel", type="int", default=30, help="Log Level (debug=10, info=20, warning=30, [error=40], critical=50)")      
       
   198     (options, args) = parser.parse_args()
       
   199     if len(args) < 1:
       
   200         parser.print_help()
       
   201         parser.error("Please supply the path to the XML content")
       
   202     if options.loglevel:
       
   203         logging.basicConfig(level=options.loglevel)  
       
   204     updatefiles(args[0], options.publishing_target)
       
   205 
       
   206 
       
   207 if __name__ == '__main__':
       
   208     sys.exit(main())
       
   209 
       
   210     
       
   211 ######################################
       
   212 # Test code
       
   213 ######################################
       
   214 
       
   215 class StubDoxyIdRedirect(object):
       
   216     def __init__(self, theDir):
       
   217         self.dict = {'struct_e_sock_1_1_t_addr_update':('struct_e_sock_1_1_t_addr_update.xml', 'ESock::TAddrUpdate'),
       
   218         'class_c_active_scheduler_1_1_t_cleanup_bundle':('class_c_active_scheduler_1_1_t_cleanup_bundle.xml', 'CActiveScheduler::TCleanupBundle'),
       
   219         'class_test':('class_test.xml', 'Test'),
       
   220         'class_test_1a99f2bbfac6c95612322b0f10e607ebe5':('cxxclass.xml', 'Test')}
       
   221     
       
   222     def lookupId(self, doxy_id):
       
   223         try:
       
   224             filename, fqn = self.dict[doxy_id]
       
   225             return (filename, fqn)
       
   226         except Exception, e:
       
   227             raise ExceptionDoxyIdRedirectLookup("StubException: %s" % e)
       
   228 
       
   229 
       
   230 class TestGuidiser(unittest.TestCase):
       
   231     def setUp(self):
       
   232         self.guidiser = Guidiser(publishing_target=Guidiser.PT_MODE, doxyidredirect=StubDoxyIdRedirect('adir'))
       
   233         self.test_dir = "guidiser_test_dir"
       
   234         
       
   235     def _create_test_data(self):
       
   236         f = open("struct_e_sock_1_1_t_addr_update.xml", "w")
       
   237         f.write(struct_e_sock_1_1_t_addr_update)
       
   238         f.close()
       
   239         os.mkdir(self.test_dir)
       
   240         f = open(os.path.join(self.test_dir, "struct_e_sock_1_1_t_addr_update.xml"), "w")
       
   241         f.write(struct_e_sock_1_1_t_addr_update)
       
   242         f.close()        
       
   243         
       
   244     def _cleanup_test_data(self):
       
   245         os.remove("struct_e_sock_1_1_t_addr_update.xml")
       
   246         shutil.rmtree(self.test_dir)
       
   247         
       
   248     def test_i_can_get_and_set_a_PT(self):
       
   249         self.assertEqual(self.guidiser.get_publishing_target(), Guidiser.PT_MODE)
       
   250         self.guidiser.set_publishing_target(Guidiser.PT_DITAOT)
       
   251         self.assertEqual(self.guidiser.get_publishing_target(), Guidiser.PT_DITAOT)
       
   252         
       
   253     def test_i_raise_an_exception_when_trying_to_set_an_invalid_PT(self):
       
   254         self.assertRaises(Exception, self.guidiser.set_publishing_target, 2) 
       
   255         
       
   256     def test_i_update_root_elements_id(self):        
       
   257         root = self.guidiser.guidise(StringIO(cxxclass))
       
   258         self.assertEqual(root.attrib['id'], "GUID-56866D87-2CE9-31EA-8FA7-F4275FDBCB93")
       
   259 
       
   260     def test_i_continue_if_passed_an_invalid_file(self):
       
   261         try:
       
   262             self.guidiser.guidise(StringIO("<cxxclass><argh</cxxclass>"))
       
   263         except Exception:
       
   264             self.fail("I shouldnt have raised an exception")
       
   265 
       
   266     def _test_keys_were_converted(self, key):
       
   267         root = self.guidiser.guidise(StringIO(cxxclass))
       
   268         for child in root.getiterator():
       
   269             if key in child.attrib:
       
   270                 self.assertTrue(child.attrib[key].startswith('GUID'))        
       
   271 
       
   272     def test_i_update_a_subelements_id(self):
       
   273         self._test_keys_were_converted('id')
       
   274 
       
   275     def test_i_update_all_hrefs_with_a_guid(self):
       
   276         self._test_keys_were_converted('href')
       
   277 
       
   278     def test_i_update_all_keyrefs_with_a_guid(self):
       
   279         self._test_keys_were_converted('keyref')
       
   280                 
       
   281     def test_based_fqn_and_one_param(self):
       
   282         self.assertTrue(self.guidiser._get_guid("RConnection::EnumerateConnections(TUint&)") ==
       
   283                         "GUID-18F9018F-78DE-3A7E-8363-B7CB101E7A99" 
       
   284                        )
       
   285         
       
   286     def test_based_fqn_and_muiltiple_params(self):
       
   287         self.assertTrue(self.guidiser._get_guid("RConnection::ProgressNotification(TSubConnectionUniqueId, TNifProgressBuf&, TRequestStatus&, TUint)") ==
       
   288                         "GUID-6E7005CF-4D8E-31CE-BAEA-21965ACC9C17" 
       
   289                        )
       
   290         
       
   291     def test_based_fqn_and_muiltiple_params_ones_a_default(self):
       
   292         self.assertTrue(self.guidiser._get_guid("RConnection::Open(RSocketServ& aSocketServer, TUint aConnectionType = KConnectionTypeDefault)") ==
       
   293                         "GUID-CE8F3FE7-14F2-3FB6-B04C-8596B5F80DFC" 
       
   294                        )
       
   295                 
       
   296     def test_based_fqn_and_muiltiple_params_ones_templated(self):
       
   297         self.assertTrue(self.guidiser._get_guid("RConnection::DataReceivedNotificationRequest(TSubConnectionUniqueId, TUint, TPckg<TUint>&, TRequestStatus&)") ==
       
   298                         "GUID-9E056551-22C2-3F85-8E3D-C11FA3B46F07" 
       
   299                        )
       
   300         
       
   301     def test_based_toplevel_class(self):
       
   302         self.assertTrue(self.guidiser._get_guid("RConnection") ==
       
   303                         "GUID-BED8A733-2ED7-31AD-A911-C1F4707C67FD" 
       
   304                        )
       
   305         
       
   306     def test_target_id(self):
       
   307         self.assertTrue(self.guidiser._get_guid("ESock::TAddrUpdate") ==
       
   308                          "GUID-E72084E6-C1CE-3388-93F7-5B7A3F506C3B"
       
   309                          )
       
   310         
       
   311     def test_topicref_href_to_topic_for_mode(self):
       
   312         self.assertEquals(self.guidiser._guidise_href("struct_e_sock_1_1_t_addr_update.xml#struct_e_sock_1_1_t_addr_update", "topicref"),
       
   313                  "GUID-E72084E6-C1CE-3388-93F7-5B7A3F506C3B"
       
   314                  )
       
   315         
       
   316     def test_topicref_href_to_topic_for_ditaot(self):
       
   317         self.guidiser.set_publishing_target(Guidiser.PT_DITAOT)
       
   318         self._create_test_data()
       
   319         try:
       
   320             self.assertEquals(self.guidiser._guidise_href("struct_e_sock_1_1_t_addr_update.xml#struct_e_sock_1_1_t_addr_update", "topicref"),
       
   321                               "GUID-E72084E6-C1CE-3388-93F7-5B7A3F506C3B.xml")
       
   322         finally:
       
   323             self._cleanup_test_data()
       
   324 
       
   325                         
       
   326     def test_topicref_href_to_map_for_mode(self):
       
   327         self.assertEquals(self.guidiser._guidise_href("ziplib.ditamap", "topicref"),
       
   328                  "GUID-7C7A889C-AE2B-31FC-A5DA-A87019E1251D"
       
   329                  )
       
   330         
       
   331     def test_topicref_href_to_map_for_ditaot(self):
       
   332         self.guidiser.set_publishing_target(Guidiser.PT_DITAOT)
       
   333         self.assertEquals(self.guidiser._guidise_href("ziplib.ditamap", "topicref"),
       
   334                  "GUID-7C7A889C-AE2B-31FC-A5DA-A87019E1251D.ditamap"
       
   335                  )
       
   336                 
       
   337     def test_xref_href_to_topic_in_same_file_for_mode(self):
       
   338         self.assertEquals(self.guidiser._guidise_href("struct_e_sock_1_1_t_addr_update.xml#struct_e_sock_1_1_t_addr_update", "xref"),
       
   339                  "GUID-E72084E6-C1CE-3388-93F7-5B7A3F506C3B"
       
   340                  )
       
   341 
       
   342     def test_xref_href_to_topic_in_same_file_for_ditaot(self):
       
   343         self.guidiser.set_publishing_target(Guidiser.PT_DITAOT)
       
   344         self.assertEquals(self.guidiser._guidise_href("struct_e_sock_1_1_t_addr_update.xml#struct_e_sock_1_1_t_addr_update", "xref"),
       
   345                  "GUID-E72084E6-C1CE-3388-93F7-5B7A3F506C3B.xml#GUID-E72084E6-C1CE-3388-93F7-5B7A3F506C3B"
       
   346                  )
       
   347 				 
       
   348     def test_xref_href_to_some_other_file_on_file_system(self):
       
   349         self.guidiser.set_publishing_target(Guidiser.PT_DITAOT)
       
   350         self.assertEquals(self.guidiser._guidise_href("../../documentation/RFCs/rfc3580.txt", "xref"),
       
   351                  "../../documentation/RFCs/rfc3580.txt"
       
   352                  )
       
   353     
       
   354     def test_i_guidise_the_id_of_a_fully_qualified_apiname(self):
       
   355         self.assertEquals(self.guidiser._guidise_id("struct_e_sock_1_1_t_addr_update"),
       
   356          "GUID-E72084E6-C1CE-3388-93F7-5B7A3F506C3B"
       
   357          )
       
   358          
       
   359     def test_id_guidise_the_id_something_that_is_not_a_fully_qualified_apiname(self):
       
   360         self.assertEquals(self.guidiser._guidise_id("commsdataobjects"),
       
   361          "GUID-2F2463E0-6C84-3FAB-8B60-57E57315FDEB"
       
   362          )
       
   363          
       
   364     def test_i_preserve_namespaces(self):  
       
   365         xml_in = """<reference ditaarch:DITAArchVersion="1.1" xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" />"""
       
   366         xml_expected = """<reference ditaarch:DITAArchVersion="1.1" xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" />"""
       
   367         root = self.guidiser.guidise(StringIO(xml_in))
       
   368         self.assertEqual(etree.tostring(root), xml_expected)
       
   369         
       
   370 class Testupdate_files(unittest.TestCase):
       
   371     
       
   372     def setUp(self):
       
   373         self.test_dir = "guidisertestdata"
       
   374         
       
   375     def tearDown(self):
       
   376         shutil.rmtree(self.test_dir)
       
   377     
       
   378     def test_i_can_update_a_file_on_the_file_sys(self):
       
   379         def reference_file_handle(mode):
       
   380             return open(os.path.join(self.test_dir, "reference.dita"), mode) 
       
   381         os.mkdir(self.test_dir)
       
   382         f = reference_file_handle("w")
       
   383         f.write(filesys_cxxclass)
       
   384         f.close()
       
   385         updatefiles(self.test_dir)
       
   386         self.assertEquals(reference_file_handle("r").read(), filesys_cxxclass_guidised)
       
   387         
       
   388 struct_e_sock_1_1_t_addr_update = """<?xml version='1.0' encoding='UTF-8' standalone='no'?>
       
   389 <!DOCTYPE cxxStruct PUBLIC "-//NOKIA//DTD DITA C++ API Struct Reference Type v0.1.0//EN" "dtd/cxxStruct.dtd" >
       
   390 <cxxStruct id="struct_coord_struct">
       
   391 	<apiName>CoordStruct</apiName>
       
   392 	<shortdesc/>
       
   393 	<cxxStructDetail>
       
   394 		<cxxStructDefinition>
       
   395 			<cxxStructAccessSpecifier value="public"/>
       
   396 			<cxxStructAPIItemLocation>
       
   397 				<cxxStructDeclarationFile name="filePath" value="C:/wip/sysdoc/tools/Doxygen/branches/DITA/test/PaulRo/linking/src/restypedef.cpp"/>
       
   398 				<cxxStructDeclarationFileLine name="lineNumber" value="10"/>
       
   399 				<cxxStructDefinitionFile name="filePath" value="C:/wip/sysdoc/tools/Doxygen/branches/DITA/test/PaulRo/linking/src/restypedef.cpp"/>
       
   400 				<cxxStructDefinitionFileLineStart name="lineNumber" value="9"/>
       
   401 				<cxxStructDefinitionFileLineEnd name="lineNumber" value="15"/>
       
   402 			</cxxStructAPIItemLocation>
       
   403 		</cxxStructDefinition>
       
   404 		<apiDesc>
       
   405 			<p>A coordinate pair. </p>
       
   406 		</apiDesc>
       
   407 	</cxxStructDetail>
       
   408 	<cxxVariable id="struct_coord_struct_1a183d7226fc5a8470ce9b9f04f9cb69bb">
       
   409 		<apiName>x</apiName>
       
   410 		<shortdesc/>
       
   411 		<cxxVariableDetail>
       
   412 			<cxxVariableDefinition>
       
   413 				<cxxVariableAccessSpecifier value="public"/>
       
   414 				<cxxVariableDeclaredType>float</cxxVariableDeclaredType>
       
   415 				<cxxVariableScopedName>CoordStruct</cxxVariableScopedName>
       
   416 				<cxxVariablePrototype>float x</cxxVariablePrototype>
       
   417 				<cxxVariableNameLookup>CoordStruct::x</cxxVariableNameLookup>
       
   418 				<cxxVariableAPIItemLocation>
       
   419 					<cxxVariableDeclarationFile name="filePath" value="C:/wip/sysdoc/tools/Doxygen/branches/DITA/test/PaulRo/linking/src/restypedef.cpp"/>
       
   420 					<cxxVariableDeclarationFileLine name="lineNumber" value="12"/>
       
   421 				</cxxVariableAPIItemLocation>
       
   422 			</cxxVariableDefinition>
       
   423 			<apiDesc>
       
   424 				<p>The x coordinate </p>
       
   425 			</apiDesc>
       
   426 		</cxxVariableDetail>
       
   427 	</cxxVariable>
       
   428 	<cxxVariable id="struct_coord_struct_1a1a5966a881bc3e76e9becf00639585ac">
       
   429 		<apiName>y</apiName>
       
   430 		<shortdesc/>
       
   431 		<cxxVariableDetail>
       
   432 			<cxxVariableDefinition>
       
   433 				<cxxVariableAccessSpecifier value="public"/>
       
   434 				<cxxVariableDeclaredType>float</cxxVariableDeclaredType>
       
   435 				<cxxVariableScopedName>CoordStruct</cxxVariableScopedName>
       
   436 				<cxxVariablePrototype>float y</cxxVariablePrototype>
       
   437 				<cxxVariableNameLookup>CoordStruct::y</cxxVariableNameLookup>
       
   438 				<cxxVariableAPIItemLocation>
       
   439 					<cxxVariableDeclarationFile name="filePath" value="C:/wip/sysdoc/tools/Doxygen/branches/DITA/test/PaulRo/linking/src/restypedef.cpp"/>
       
   440 					<cxxVariableDeclarationFileLine name="lineNumber" value="14"/>
       
   441 				</cxxVariableAPIItemLocation>
       
   442 			</cxxVariableDefinition>
       
   443 			<apiDesc>
       
   444 				<p>The y coordinate </p>
       
   445 			</apiDesc>
       
   446 		</cxxVariableDetail>
       
   447 	</cxxVariable>
       
   448 </cxxStruct>"""
       
   449         
       
   450 filesys_cxxclass = """<?xml version='1.0' encoding='UTF-8' standalone='no'?>
       
   451 <!DOCTYPE cxxClass PUBLIC "-//NOKIA//DTD DITA C++ API Class Reference Type v0.1.0//EN" "dtd/cxxClass.dtd" >
       
   452 <cxxClass id="class_c_active_scheduler_1_1_t_cleanup_bundle">
       
   453     <apiName>CActiveScheduler::TCleanupBundle</apiName>
       
   454     <shortdesc/>
       
   455     <cxxClassDetail>
       
   456         <cxxClassDefinition>
       
   457             <cxxClassAccessSpecifier value="private"/>
       
   458             <cxxClassAPIItemLocation>
       
   459                 <cxxClassDeclarationFile name="filePath" value="K:/epoc32/include/e32base.h"/>
       
   460                 <cxxClassDeclarationFileLine name="lineNumber" value="2832"/>
       
   461                 <cxxClassDefinitionFile name="filePath" value="K:/sf/os/commsfw/datacommsserver/esockserver/csock/CS_CLI.CPP"/>
       
   462                 <cxxClassDefinitionFileLineStart name="lineNumber" value="2831"/>
       
   463                 <cxxClassDefinitionFileLineEnd name="lineNumber" value="2836"/>
       
   464             </cxxClassAPIItemLocation>
       
   465         </cxxClassDefinition>
       
   466         <apiDesc/>
       
   467     </cxxClassDetail>
       
   468     <cxxVariable id="class_c_active_scheduler_1_1_t_cleanup_bundle_1aaa7a637534aa0b9164dda2816be6fbf4">
       
   469         <apiName>iCleanupPtr</apiName>
       
   470         <shortdesc/>
       
   471         <cxxVariableDetail>
       
   472             <cxxVariableDefinition>
       
   473                 <cxxVariableAccessSpecifier value="public"/>
       
   474                 <cxxVariableDeclaredType>
       
   475                     <apiRelation keyref="class_c_cleanup">CCleanup</apiRelation> *</cxxVariableDeclaredType>
       
   476                 <cxxVariableScopedName>CActiveScheduler::TCleanupBundle</cxxVariableScopedName>
       
   477                 <cxxVariablePrototype>CCleanup * iCleanupPtr</cxxVariablePrototype>
       
   478                 <cxxVariableNameLookup>CActiveScheduler::TCleanupBundle::iCleanupPtr</cxxVariableNameLookup>
       
   479                 <cxxVariableAPIItemLocation>
       
   480                     <cxxVariableDeclarationFile name="filePath" value="K:/epoc32/include/e32base.h"/>
       
   481                     <cxxVariableDeclarationFileLine name="lineNumber" value="2834"/>
       
   482                 </cxxVariableAPIItemLocation>
       
   483             </cxxVariableDefinition>
       
   484             <apiDesc/>
       
   485         </cxxVariableDetail>
       
   486     </cxxVariable>
       
   487     <cxxVariable id="class_c_active_scheduler_1_1_t_cleanup_bundle_1ad750b8dbf966def2486a52b6c3d236fc">
       
   488         <apiName>iDummyInt</apiName>
       
   489         <shortdesc/>
       
   490         <cxxVariableDetail>
       
   491             <cxxVariableDefinition>
       
   492                 <cxxVariableAccessSpecifier value="public"/>
       
   493                 <cxxVariableDeclaredType>
       
   494                     <apiRelation keyref="_c_s___c_l_i_8_c_p_p_1abb88f5378e8305d934297176fe5fa298">TInt</apiRelation>
       
   495                 </cxxVariableDeclaredType>
       
   496                 <cxxVariableScopedName>CActiveScheduler::TCleanupBundle</cxxVariableScopedName>
       
   497                 <cxxVariablePrototype>TInt iDummyInt</cxxVariablePrototype>
       
   498                 <cxxVariableNameLookup>CActiveScheduler::TCleanupBundle::iDummyInt</cxxVariableNameLookup>
       
   499                 <cxxVariableAPIItemLocation>
       
   500                     <cxxVariableDeclarationFile name="filePath" value="K:/epoc32/include/e32base.h"/>
       
   501                     <cxxVariableDeclarationFileLine name="lineNumber" value="2835"/>
       
   502                 </cxxVariableAPIItemLocation>
       
   503             </cxxVariableDefinition>
       
   504             <apiDesc/>
       
   505         </cxxVariableDetail>
       
   506     </cxxVariable>
       
   507 </cxxClass>"""
       
   508 
       
   509 filesys_cxxclass_guidised = """<?xml version="1.0" encoding="UTF-8"?>
       
   510 <!DOCTYPE cxxClass PUBLIC "-//NOKIA//DTD DITA C++ API Class Reference Type v0.1.0//EN" "dtd/cxxClass.dtd">
       
   511 <cxxClass id="GUID-83FD90ED-B2F7-3ED5-ABC5-83ED6A3F1C2F">
       
   512     <apiName>CActiveScheduler::TCleanupBundle</apiName>
       
   513     <shortdesc />
       
   514     <cxxClassDetail>
       
   515         <cxxClassDefinition>
       
   516             <cxxClassAccessSpecifier value="private" />
       
   517             <cxxClassAPIItemLocation>
       
   518                 <cxxClassDeclarationFile name="filePath" value="K:/epoc32/include/e32base.h" />
       
   519                 <cxxClassDeclarationFileLine name="lineNumber" value="2832" />
       
   520                 <cxxClassDefinitionFile name="filePath" value="K:/sf/os/commsfw/datacommsserver/esockserver/csock/CS_CLI.CPP" />
       
   521                 <cxxClassDefinitionFileLineStart name="lineNumber" value="2831" />
       
   522                 <cxxClassDefinitionFileLineEnd name="lineNumber" value="2836" />
       
   523             </cxxClassAPIItemLocation>
       
   524         </cxxClassDefinition>
       
   525         <apiDesc />
       
   526     </cxxClassDetail>
       
   527     <cxxVariable id="GUID-903F7E6D-EFFE-3A37-9348-B9FE3A27AF4A">
       
   528         <apiName>iCleanupPtr</apiName>
       
   529         <shortdesc />
       
   530         <cxxVariableDetail>
       
   531             <cxxVariableDefinition>
       
   532                 <cxxVariableAccessSpecifier value="public" />
       
   533                 <cxxVariableDeclaredType>
       
   534                     <apiRelation keyref="GUID-3BB23EB1-2F65-378D-918B-1FBBD6E46C90">CCleanup</apiRelation> *</cxxVariableDeclaredType>
       
   535                 <cxxVariableScopedName>CActiveScheduler::TCleanupBundle</cxxVariableScopedName>
       
   536                 <cxxVariablePrototype>CCleanup * iCleanupPtr</cxxVariablePrototype>
       
   537                 <cxxVariableNameLookup>CActiveScheduler::TCleanupBundle::iCleanupPtr</cxxVariableNameLookup>
       
   538                 <cxxVariableAPIItemLocation>
       
   539                     <cxxVariableDeclarationFile name="filePath" value="K:/epoc32/include/e32base.h" />
       
   540                     <cxxVariableDeclarationFileLine name="lineNumber" value="2834" />
       
   541                 </cxxVariableAPIItemLocation>
       
   542             </cxxVariableDefinition>
       
   543             <apiDesc />
       
   544         </cxxVariableDetail>
       
   545     </cxxVariable>
       
   546     <cxxVariable id="GUID-DA4580F4-EBCC-3FA2-A856-810EAFC82236">
       
   547         <apiName>iDummyInt</apiName>
       
   548         <shortdesc />
       
   549         <cxxVariableDetail>
       
   550             <cxxVariableDefinition>
       
   551                 <cxxVariableAccessSpecifier value="public" />
       
   552                 <cxxVariableDeclaredType>
       
   553                     <apiRelation keyref="GUID-1A4B29B0-5E06-39E5-A0A8-4A33E093C872">TInt</apiRelation>
       
   554                 </cxxVariableDeclaredType>
       
   555                 <cxxVariableScopedName>CActiveScheduler::TCleanupBundle</cxxVariableScopedName>
       
   556                 <cxxVariablePrototype>TInt iDummyInt</cxxVariablePrototype>
       
   557                 <cxxVariableNameLookup>CActiveScheduler::TCleanupBundle::iDummyInt</cxxVariableNameLookup>
       
   558                 <cxxVariableAPIItemLocation>
       
   559                     <cxxVariableDeclarationFile name="filePath" value="K:/epoc32/include/e32base.h" />
       
   560                     <cxxVariableDeclarationFileLine name="lineNumber" value="2835" />
       
   561                 </cxxVariableAPIItemLocation>
       
   562             </cxxVariableDefinition>
       
   563             <apiDesc />
       
   564         </cxxVariableDetail>
       
   565     </cxxVariable>
       
   566 </cxxClass>"""
       
   567         
       
   568 cxxclass = """<?xml version='1.0' encoding='UTF-8' standalone='no'?>
       
   569 <!DOCTYPE cxxClass PUBLIC "-//NOKIA//DTD DITA C++ API Class Reference Type v0.1.0//EN" "dtd/cxxClass.dtd" >
       
   570 <cxxClass id="class_test">
       
   571 	<apiName>Test</apiName>
       
   572 	<shortdesc/>
       
   573 	<cxxClassDetail>
       
   574 		<cxxClassDefinition>
       
   575 			<cxxClassAccessSpecifier value="public"/>
       
   576 			<cxxClassAPIItemLocation>
       
   577 				<cxxClassDeclarationFile name="filePath" value="C:/wip/sysdoc/tools/Doxygen/branches/DITA/test/PaulRo/linking/src/autolink.cpp"/>
       
   578 				<cxxClassDeclarationFileLine name="lineNumber" value="59"/>
       
   579 				<cxxClassDefinitionFile name="filePath" value="C:/wip/sysdoc/tools/Doxygen/branches/DITA/test/PaulRo/linking/src/autolink.cpp"/>
       
   580 				<cxxClassDefinitionFileLineStart name="lineNumber" value="58"/>
       
   581 				<cxxClassDefinitionFileLineEnd name="lineNumber" value="74"/>
       
   582 			</cxxClassAPIItemLocation>
       
   583 		</cxxClassDefinition>
       
   584 		<apiDesc>
       
   585         <p>Points to function <xref href="class_test.xml#class_test_1a99f2bbfac6c95612322b0f10e607ebe5">Test()</xref></p>
       
   586 		</apiDesc>
       
   587 	</cxxClassDetail>
       
   588 	<cxxFunction id="class_test_1a99f2bbfac6c95612322b0f10e607ebe5">
       
   589 		<apiName>Test</apiName>
       
   590 		<shortdesc/>
       
   591 		<cxxFunctionDetail>
       
   592 			<cxxFunctionDefinition>
       
   593 				<cxxFunctionAccessSpecifier value="public"/>
       
   594 				<cxxFunctionConstructor/>
       
   595 				<cxxFunctionDeclaredType/>
       
   596 				<cxxFunctionScopedName>Test</cxxFunctionScopedName>
       
   597 				<cxxFunctionPrototype>Test()</cxxFunctionPrototype>
       
   598 				<cxxFunctionNameLookup>Test::Test()</cxxFunctionNameLookup>
       
   599 				<cxxFunctionParameters/>
       
   600 				<cxxFunctionAPIItemLocation>
       
   601 					<cxxFunctionDeclarationFile name="filePath" value="C:/wip/sysdoc/tools/Doxygen/branches/DITA/test/PaulRo/linking/src/autolink.cpp"/>
       
   602 					<cxxFunctionDeclarationFileLine name="lineNumber" value="61"/>
       
   603 					<cxxFunctionDefinitionFile name="filePath" value="C:/wip/sysdoc/tools/Doxygen/branches/DITA/test/PaulRo/linking/src/autolink.cpp"/>
       
   604 					<cxxFunctionDefinitionFileLineStart name="lineNumber" value="77"/>
       
   605 					<cxxFunctionDefinitionFileLineEnd name="lineNumber" value="77"/>
       
   606 				</cxxFunctionAPIItemLocation>
       
   607 			</cxxFunctionDefinition>
       
   608 			<apiDesc>
       
   609 				<p>details. </p>
       
   610 			</apiDesc>
       
   611 		</cxxFunctionDetail>
       
   612 	</cxxFunction>
       
   613 </cxxClass>"""