Skip to content

Commit 41539b1

Browse files
committed
issue #11016 Faulty xml generated when markdown header is too deep.
1 parent 509f6cc commit 41539b1

6 files changed

Lines changed: 85 additions & 31 deletions

File tree

addon/doxmlparser/doxmlparser/compound.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26714,7 +26714,7 @@ class tableofcontentsType(GeneratedsSuper):
2671426714
__hash__ = GeneratedsSuper.__hash__
2671526715
subclass = None
2671626716
superclass = None
26717-
def __init__(self, tocsect=None, gds_collector_=None, **kwargs_):
26717+
def __init__(self, tocsect=None, tableofcontents=None, gds_collector_=None, **kwargs_):
2671826718
self.gds_collector_ = gds_collector_
2671926719
self.gds_elementtree_node_ = None
2672026720
self.original_tagname_ = None
@@ -26725,6 +26725,11 @@ def __init__(self, tocsect=None, gds_collector_=None, **kwargs_):
2672526725
else:
2672626726
self.tocsect = tocsect
2672726727
self.tocsect_nsprefix_ = None
26728+
if tableofcontents is None:
26729+
self.tableofcontents = []
26730+
else:
26731+
self.tableofcontents = tableofcontents
26732+
self.tableofcontents_nsprefix_ = None
2672826733
def factory(*args_, **kwargs_):
2672926734
if CurrentSubclassModule_ is not None:
2673026735
subclass = getSubclassFromModule_(
@@ -26750,9 +26755,20 @@ def insert_tocsect_at(self, index, value):
2675026755
self.tocsect.insert(index, value)
2675126756
def replace_tocsect_at(self, index, value):
2675226757
self.tocsect[index] = value
26758+
def get_tableofcontents(self):
26759+
return self.tableofcontents
26760+
def set_tableofcontents(self, tableofcontents):
26761+
self.tableofcontents = tableofcontents
26762+
def add_tableofcontents(self, value):
26763+
self.tableofcontents.append(value)
26764+
def insert_tableofcontents_at(self, index, value):
26765+
self.tableofcontents.insert(index, value)
26766+
def replace_tableofcontents_at(self, index, value):
26767+
self.tableofcontents[index] = value
2675326768
def hasContent_(self):
2675426769
if (
26755-
self.tocsect
26770+
self.tocsect or
26771+
self.tableofcontents
2675626772
):
2675726773
return True
2675826774
else:
@@ -26790,6 +26806,9 @@ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='',
2679026806
for tocsect_ in self.tocsect:
2679126807
namespaceprefix_ = self.tocsect_nsprefix_ + ':' if (UseCapturedNS_ and self.tocsect_nsprefix_) else ''
2679226808
tocsect_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='tocsect', pretty_print=pretty_print)
26809+
for tableofcontents_ in self.tableofcontents:
26810+
namespaceprefix_ = self.tableofcontents_nsprefix_ + ':' if (UseCapturedNS_ and self.tableofcontents_nsprefix_) else ''
26811+
tableofcontents_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='tableofcontents', pretty_print=pretty_print)
2679326812
def build(self, node, gds_collector_=None):
2679426813
self.gds_collector_ = gds_collector_
2679526814
if SaveElementTreeNode:
@@ -26809,6 +26828,11 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collec
2680926828
obj_.build(child_, gds_collector_=gds_collector_)
2681026829
self.tocsect.append(obj_)
2681126830
obj_.original_tagname_ = 'tocsect'
26831+
elif nodeName_ == 'tableofcontents':
26832+
obj_ = tableofcontentsType.factory(parent_object_=self)
26833+
obj_.build(child_, gds_collector_=gds_collector_)
26834+
self.tableofcontents.append(obj_)
26835+
obj_.original_tagname_ = 'tableofcontents'
2681226836
# end class tableofcontentsType
2681326837

2681426838

src/docnode.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5727,7 +5727,7 @@ int DocSection::parse()
57275727
else if (retval==RetVal_Subsubsection && m_level<=2)
57285728
{
57295729
if ((m_level <= 1) &&
5730-
AnchorGenerator::instance().isGenerated(parser()->context.token->sectionId.str()))
5730+
!AnchorGenerator::instance().isGenerated(parser()->context.token->sectionId.str()))
57315731
{
57325732
warn_doc_error(parser()->context.fileName,
57335733
parser()->tokenizer.getLineNr(),
@@ -5747,7 +5747,7 @@ int DocSection::parse()
57475747
else if (retval==RetVal_Paragraph && m_level<=3)
57485748
{
57495749
if ((m_level <= 2) &&
5750-
AnchorGenerator::instance().isGenerated(parser()->context.token->sectionId.str()))
5750+
!AnchorGenerator::instance().isGenerated(parser()->context.token->sectionId.str()))
57515751
{
57525752
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),
57535753
"Unexpected paragraph command found inside %s!",
@@ -5766,7 +5766,7 @@ int DocSection::parse()
57665766
else if (retval==RetVal_SubParagraph && m_level<=4)
57675767
{
57685768
if ((m_level <= 3) &&
5769-
AnchorGenerator::instance().isGenerated(parser()->context.token->sectionId.str()))
5769+
!AnchorGenerator::instance().isGenerated(parser()->context.token->sectionId.str()))
57705770
{
57715771
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),
57725772
"Unexpected subparagraph command found inside %s!",
@@ -5786,7 +5786,7 @@ int DocSection::parse()
57865786
else if (retval==RetVal_SubSubParagraph && m_level<=5)
57875787
{
57885788
if ((m_level <= 4) &&
5789-
AnchorGenerator::instance().isGenerated(parser()->context.token->sectionId.str()))
5789+
!AnchorGenerator::instance().isGenerated(parser()->context.token->sectionId.str()))
57905790
{
57915791
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),
57925792
"Unexpected subsubparagraph command found inside %s!",

src/xmldocvisitor.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ static void visitPostEnd(TextStream &t, const char *cmd)
149149

150150
XmlDocVisitor::XmlDocVisitor(TextStream &t,OutputCodeList &ci,const QCString &langExt)
151151
: m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE),
152-
m_langExt(langExt)
152+
m_langExt(langExt), m_sectionLevel(0)
153153
{
154154
}
155155

@@ -687,15 +687,29 @@ void XmlDocVisitor::operator()(const DocSimpleListItem &li)
687687
void XmlDocVisitor::operator()(const DocSection &s)
688688
{
689689
if (m_hide) return;
690-
m_t << "<sect" << s.level() << " id=\"" << s.file();
691-
if (!s.anchor().isEmpty()) m_t << "_1" << s.anchor();
692-
m_t << "\">\n";
690+
int orgSectionLevel = m_sectionLevel;
691+
QCString sectId = s.file();
692+
if (!s.anchor().isEmpty()) sectId += "_1"+s.anchor();
693+
while (m_sectionLevel+1<s.level()) // fix missing intermediate levels
694+
{
695+
m_sectionLevel++;
696+
m_t << "<sect" << m_sectionLevel << " id=\"" << sectId << "_1s" << m_sectionLevel << "\">";
697+
}
698+
m_sectionLevel++;
699+
m_t << "<sect" << s.level() << " id=\"" << sectId << "\">\n";
693700
if (s.title())
694701
{
695702
std::visit(*this,*s.title());
696703
}
697704
visitChildren(s);
698-
m_t << "</sect" << s.level() << ">\n";
705+
m_t << "</sect" << s.level() << ">";
706+
m_sectionLevel--;
707+
while (orgSectionLevel<m_sectionLevel) // fix missing intermediate levels
708+
{
709+
m_t << "</sect" << m_sectionLevel << ">";
710+
m_sectionLevel--;
711+
}
712+
m_t << "\n";
699713
}
700714

701715
void XmlDocVisitor::operator()(const DocHtmlList &s)

src/xmldocvisitor.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,10 @@ class XmlDocVisitor : public DocVisitor
127127

128128
TextStream &m_t;
129129
OutputCodeList &m_ci;
130-
bool m_insidePre;
131-
bool m_hide;
130+
bool m_insidePre = false;
131+
bool m_hide = false;
132132
QCString m_langExt;
133+
int m_sectionLevel;
133134
};
134135

135136
#endif

src/xmlgen.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,8 +2028,12 @@ static void generateXMLForPage(PageDef *pd,TextStream &ti,bool isExample)
20282028
const SectionRefs &sectionRefs = pd->getSectionRefs();
20292029
if (pd->localToc().isXmlEnabled() && !sectionRefs.empty())
20302030
{
2031-
t << " <tableofcontents>\n";
20322031
int level=1;
2032+
int indent=0;
2033+
auto writeIndent = [&]() { for (int i=0;i<4+indent*2;i++) t << " "; };
2034+
auto incIndent = [&](const char *text) { writeIndent(); t << text << "\n"; indent++; };
2035+
auto decIndent = [&](const char *text) { indent--; writeIndent(); t << text << "\n"; };
2036+
incIndent("<tableofcontents>");
20332037
int maxLevel = pd->localToc().xmlLevel();
20342038
BoolVector inLi(maxLevel+1,false);
20352039
for (const SectionInfo *si : sectionRefs)
@@ -2042,42 +2046,50 @@ static void generateXMLForPage(PageDef *pd,TextStream &ti,bool isExample)
20422046
{
20432047
for (int l=level;l<nextLevel;l++)
20442048
{
2045-
if (l < maxLevel) t << " <tableofcontents>\n";
2049+
if (l < maxLevel) incIndent("<tableofcontents>");
20462050
}
20472051
}
20482052
else if (nextLevel<level)
20492053
{
20502054
for (int l=level;l>nextLevel;l--)
20512055
{
2052-
if (l <= maxLevel && inLi[l]) t << " </tocsect>\n";
2056+
if (l <= maxLevel && inLi[l]) decIndent("</tocsect>");
20532057
inLi[l]=false;
2054-
if (l <= maxLevel) t << " </tableofcontents>\n";
2058+
if (l <= maxLevel) decIndent("</tableofcontents>");
20552059
}
20562060
}
20572061
if (nextLevel <= maxLevel)
20582062
{
2059-
if (inLi[nextLevel]) t << " </tocsect>\n";
2063+
if (inLi[nextLevel])
2064+
{
2065+
decIndent("</tocsect>");
2066+
}
2067+
else if (level>nextLevel)
2068+
{
2069+
decIndent("</tableofcontents>");
2070+
incIndent("<tableofcontents>");
2071+
}
20602072
QCString titleDoc = convertToXML(si->title());
20612073
QCString label = convertToXML(si->label());
20622074
if (titleDoc.isEmpty()) titleDoc = label;
2063-
t << " <tocsect>\n";
2064-
t << " <name>" << titleDoc << "</name>\n";
2065-
t << " <reference>" << convertToXML(pageName) << "_1" << label << "</reference>\n";
2075+
incIndent("<tocsect>");
2076+
writeIndent(); t << "<name>" << titleDoc << "</name>\n";
2077+
writeIndent(); t << "<reference>" << convertToXML(pageName) << "_1" << label << "</reference>\n";
20662078
inLi[nextLevel]=true;
20672079
level = nextLevel;
20682080
}
20692081
}
20702082
}
20712083
while (level>1 && level <= maxLevel)
20722084
{
2073-
if (inLi[level]) t << " </tocsect>\n";
2085+
if (inLi[level]) decIndent("</tocsect>");
20742086
inLi[level]=false;
2075-
t << " </tableofcontents>\n";
2087+
decIndent("</tableofcontents>");
20762088
level--;
20772089
}
2078-
if (level <= maxLevel && inLi[level]) t << " </tocsect>\n";
2090+
if (level <= maxLevel && inLi[level]) decIndent("</tocsect>");
20792091
inLi[level]=false;
2080-
t << " </tableofcontents>\n";
2092+
decIndent("</tableofcontents>");
20812093
}
20822094
t << " <briefdescription>\n";
20832095
writeXMLDocBlock(t,pd->briefFile(),pd->briefLine(),pd,nullptr,pd->briefDescription());

templates/xml/compound.xsd

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@
399399

400400
<xsd:complexType name="docSect2Type" mixed="true">
401401
<xsd:sequence>
402-
<xsd:element name="title" type="docTitleType" />
402+
<xsd:element name="title" type="docTitleType" minOccurs="0" />
403403
<xsd:choice maxOccurs="unbounded">
404404
<xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
405405
<xsd:element name="sect3" type="docSect3Type" minOccurs="0" maxOccurs="unbounded" />
@@ -411,7 +411,7 @@
411411

412412
<xsd:complexType name="docSect3Type" mixed="true">
413413
<xsd:sequence>
414-
<xsd:element name="title" type="docTitleType" />
414+
<xsd:element name="title" type="docTitleType" minOccurs="0" />
415415
<xsd:choice maxOccurs="unbounded">
416416
<xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
417417
<xsd:element name="sect4" type="docSect4Type" minOccurs="0" maxOccurs="unbounded" />
@@ -423,7 +423,7 @@
423423

424424
<xsd:complexType name="docSect4Type" mixed="true">
425425
<xsd:sequence>
426-
<xsd:element name="title" type="docTitleType" />
426+
<xsd:element name="title" type="docTitleType" minOccurs="0" />
427427
<xsd:choice maxOccurs="unbounded">
428428
<xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
429429
<xsd:element name="sect5" type="docSect5Type" minOccurs="0" maxOccurs="unbounded" />
@@ -435,7 +435,7 @@
435435

436436
<xsd:complexType name="docSect5Type" mixed="true">
437437
<xsd:sequence>
438-
<xsd:element name="title" type="docTitleType" />
438+
<xsd:element name="title" type="docTitleType" minOccurs="0" />
439439
<xsd:choice maxOccurs="unbounded">
440440
<xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
441441
<xsd:element name="sect6" type="docSect6Type" minOccurs="0" maxOccurs="unbounded" />
@@ -447,7 +447,7 @@
447447

448448
<xsd:complexType name="docSect6Type" mixed="true">
449449
<xsd:sequence>
450-
<xsd:element name="title" type="docTitleType" />
450+
<xsd:element name="title" type="docTitleType" minOccurs="0" />
451451
<xsd:choice maxOccurs="unbounded">
452452
<xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
453453
<xsd:element name="internal" type="docInternalS6Type" minOccurs="0" />
@@ -869,7 +869,10 @@
869869

870870
<xsd:complexType name="tableofcontentsType">
871871
<xsd:sequence>
872-
<xsd:element name="tocsect" type="tableofcontentsKindType" minOccurs="1" maxOccurs="unbounded" />
872+
<xsd:choice>
873+
<xsd:element name="tocsect" type="tableofcontentsKindType" minOccurs="1" maxOccurs="unbounded" />
874+
<xsd:element name="tableofcontents" type="tableofcontentsType" minOccurs="0" maxOccurs="unbounded" />
875+
</xsd:choice>
873876
</xsd:sequence>
874877
</xsd:complexType>
875878

0 commit comments

Comments
 (0)