Skip to content

Commit d10bdde

Browse files
Changes to handle more strict validation of XML:
1. Add namespace="##other" to xs:any attributes 2. Add mixed="true" to classes derived from string to allow content.
1 parent a36f020 commit d10bdde

File tree

4 files changed

+71
-30
lines changed

4 files changed

+71
-30
lines changed

test/c++17/testFunctional

-314 KB
Binary file not shown.

test/testXMLcd.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ using namespace classdesc;
1919

2020
enum EnumFoo {ea, eb, ec=12, ed};
2121

22+
// check that something derived from string can have content in their tags
23+
struct String: public std::string
24+
{
25+
String(): std::string("dummy content") {}
26+
};
27+
2228
struct Foo
2329
{
2430
char ch;
@@ -27,6 +33,7 @@ struct Foo
2733
int b;
2834
bool bf, bt;
2935
std::string c;
36+
String C;
3037
std::vector<std::string> c1;
3138
int d[3];
3239
int d1[3][2];

xsd_generate_base.h

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ namespace classdesc
2727
{
2828
bool complete; //set to true if current type definition is complete
2929
bool sequenceAdded;
30+
bool derivedFromString; //True if derived from string - expect data
3031
string name, description, baseClass;
3132
TypeBeingAddedTo(const string& name="", const string& d="", bool complete=false):
32-
complete(complete), sequenceAdded(false), name(name), description(d) {}
33+
complete(complete), sequenceAdded(false), derivedFromString(false), name(name), description(d) {}
3334
};
3435

35-
std::vector<TypeBeingAddedTo> typeBeingaddedTo;
36+
std::vector<TypeBeingAddedTo> typeBeingAddedTo;
3637
std::set<string> written; // record when a type is written
3738

3839
void outputType(std::ostream& o, const string& type)
@@ -62,37 +63,61 @@ namespace classdesc
6263

6364
xsd_generate_t(): optional(false) {}
6465

66+
void setTypeBeingAddedToIsDerivedFromString() {
67+
if (!typeBeingAddedTo.back().complete)
68+
{
69+
// replace first open tag with one with mixed attribute
70+
std::string type=typeBeingAddedTo.back().name;
71+
std::string& def=xsdDefs[type];
72+
std::string::size_type n=def.find('>');
73+
if (n!=std::string::npos)
74+
def=" <xs:complexType mixed=\"true\" name=\""+type+"\">"+
75+
def.substr(n+1);
76+
}
77+
}
78+
6579
/// add an attribute \a name with XSD type \a memberType
6680
void addMember(const string& name, const string& memberType)
6781
{
6882
if (!name.empty() &&
69-
!typeBeingaddedTo.empty() && !typeBeingaddedTo.back().complete)
83+
!typeBeingAddedTo.empty() && !typeBeingAddedTo.back().complete)
7084
{
71-
if (!typeBeingaddedTo.back().sequenceAdded)
72-
xsdDefs[typeBeingaddedTo.back().name]+=" <xs:sequence>\n";
73-
typeBeingaddedTo.back().sequenceAdded=true;
74-
xsdDefs[typeBeingaddedTo.back().name]+=
85+
if (!typeBeingAddedTo.back().sequenceAdded)
86+
xsdDefs[typeBeingAddedTo.back().name]+=" <xs:sequence>\n";
87+
typeBeingAddedTo.back().sequenceAdded=true;
88+
xsdDefs[typeBeingAddedTo.back().name]+=
7589
" <xs:element name=\""+name+"\" type=\""
7690
+memberType+(optional?"\" minOccurs=\"0":"")+"\"/>\n";
77-
addDependency(typeBeingaddedTo.back().name, memberType);
91+
addDependency(typeBeingAddedTo.back().name, memberType);
7892
}
7993
}
8094

8195
/// add a base class to the current definition
8296
void addBase(const string& base)
8397
{
84-
if (!typeBeingaddedTo.empty() && !typeBeingaddedTo.back().complete)
98+
if (!typeBeingAddedTo.empty() && !typeBeingAddedTo.back().complete)
8599
{
86-
if (typeBeingaddedTo.back().baseClass.empty())
100+
if (typeBeingAddedTo.back().baseClass.empty())
87101
{
88-
xsdDefs[typeBeingaddedTo.back().name]+=
102+
// classes derived from std::string (explicity
103+
// qualified), can also have string data in the content
104+
// of the XML tag
105+
if (base=="xs::string")
106+
{
107+
string& def=xsdDefs[typeBeingAddedTo.back().name];
108+
std::string::size_type endFirstTag=def.find('>');
109+
if (endFirstTag!=string::npos && endFirstTag>0)
110+
def=def.substr(0,endFirstTag-1)+" mixed=\"true\" "+
111+
def.substr(endFirstTag);
112+
}
113+
xsdDefs[typeBeingAddedTo.back().name]+=
89114
" <xs:complexContent>\n"
90115
" <xs:extension base=\""+base+"\">\n";
91-
typeBeingaddedTo.back().baseClass=base;
116+
typeBeingAddedTo.back().baseClass=base;
92117
}
93-
else if (typeBeingaddedTo.back().baseClass!=base)
118+
else if (typeBeingAddedTo.back().baseClass!=base)
94119
throw exception
95-
("Multiple inheritance not supported: "+typeBeingaddedTo.back().name);
120+
("Multiple inheritance not supported: "+typeBeingAddedTo.back().name);
96121
}
97122
}
98123

@@ -109,35 +134,40 @@ namespace classdesc
109134
/// xsd_generate()
110135
void openType(const string& type, const string& description)
111136
{
112-
typeBeingaddedTo.push_back
137+
typeBeingAddedTo.push_back
113138
(TypeBeingAddedTo(type, description, xsdDefs.count(type)>0));
114-
if (!typeBeingaddedTo.back().complete)
115-
xsdDefs[type]=" <xs:complexType name=\""+type+"\">\n";
139+
if (!typeBeingAddedTo.back().complete)
140+
{
141+
xsdDefs[type]=" <xs:complexType name=\""+type+"\">\n";
142+
}
116143
}
117144
/// complete type definition - matching last nested openType
118145
void closeType()
119146
{
120-
if (!typeBeingaddedTo.empty() && !typeBeingaddedTo.back().complete)
147+
if (!typeBeingAddedTo.empty() && !typeBeingAddedTo.back().complete)
121148
{
122149
// allow schema to be extensible - either for polymorphic
123150
// reasons, or for future extensibility
124-
xsdDefs[typeBeingaddedTo.back().name]+=
125-
" <xs:any minOccurs=\"0\" "
126-
"maxOccurs=\"unbounded\" processContents=\"lax\"/>\n";
127-
if (typeBeingaddedTo.back().sequenceAdded)
128-
xsdDefs[typeBeingaddedTo.back().name]+=" </xs:sequence>\n";
129-
if (!typeBeingaddedTo.back().baseClass.empty())
130-
xsdDefs[typeBeingaddedTo.back().name]+=" </xs:extension>\n"
151+
// namespace attribute to solve Unique Particle Attribution (UPA) rule in XSD 1.0
152+
if (typeBeingAddedTo.back().baseClass.empty())
153+
xsdDefs[typeBeingAddedTo.back().name]+=
154+
" <xs:any minOccurs=\"0\" "
155+
"namespace=\"##other\" "
156+
"maxOccurs=\"unbounded\" processContents=\"lax\"/>\n";
157+
if (typeBeingAddedTo.back().sequenceAdded)
158+
xsdDefs[typeBeingAddedTo.back().name]+=" </xs:sequence>\n";
159+
if (!typeBeingAddedTo.back().baseClass.empty())
160+
xsdDefs[typeBeingAddedTo.back().name]+=" </xs:extension>\n"
131161
" </xs:complexContent>\n";
132-
xsdDefs[typeBeingaddedTo.back().name]+=" </xs:complexType>\n";
162+
xsdDefs[typeBeingAddedTo.back().name]+=" </xs:complexType>\n";
133163
}
134-
typeBeingaddedTo.pop_back();
164+
typeBeingAddedTo.pop_back();
135165
}
136166

137167
string currentDescription() const
138168
{
139-
if (!typeBeingaddedTo.empty())
140-
return typeBeingaddedTo.back().description;
169+
if (!typeBeingAddedTo.empty())
170+
return typeBeingAddedTo.back().description;
141171
else
142172
return "";
143173
}
@@ -459,7 +489,11 @@ namespace classdesc
459489

460490
template <class T>
461491
void xsd_generate_onbase(xsd_generate_t& g, const string& d, T a)
462-
{xsd_generate(g,d+basename<T>(),a);}
492+
{
493+
if (is_string<T>::value)
494+
g.setTypeBeingAddedToIsDerivedFromString();
495+
xsd_generate(g,d+basename<T>(),a);
496+
}
463497

464498
template <class T>
465499
typename enable_if<EverythingElse<T>, void>::T

0 commit comments

Comments
 (0)