diff --git a/uppsrc/Core/XML.cpp b/uppsrc/Core/XML.cpp index 8f4ab01e6..b27d3373e 100644 --- a/uppsrc/Core/XML.cpp +++ b/uppsrc/Core/XML.cpp @@ -949,6 +949,7 @@ bool ShouldPreserve(const String& s) return false; } +/* String AsXML(const XmlNode& node, dword style) { StringBuffer r; @@ -995,6 +996,84 @@ String AsXML(const XmlNode& node, dword style) } return r; } +*/ + +static void sAsXML(Stream& out, const XmlNode& node, dword style, const String& indent) +{ + if(style & XML_HEADER) { + String h = XmlHeader(); + if(!(style & XML_PRETTY)) + h.Trim(h.GetCount() - 2); + out << h; + } + if(style & XML_DOCTYPE) + for(int i = 0; i < node.GetCount(); i++) { + const XmlNode& m = node.Node(i); + if(m.GetType() == XML_TAG) { + String h = XmlDocType(m.GetText()); + h.Trim(h.GetCount() - 2); + out << h; + break; + } + } + style &= ~(XML_HEADER|XML_DOCTYPE); + switch(node.GetType()) { + case XML_PI: + out << indent << "\r\n"; + break; + case XML_DECL: + out << indent << "\r\n"; + break; + case XML_COMMENT: + out << indent << "\r\n"; + break; + case XML_DOC: + for(int i = 0; i < node.GetCount(); i++) + sAsXML(out, node.Node(i), style, indent); + break; + case XML_TEXT: + out << DeXml(node.GetText()); + break; + case XML_TAG: + XmlTag tag(node.GetText()); + for(int i = 0; i < node.GetAttrCount(); i++) + tag(node.AttrId(i), node.Attr(i)); + if(node.GetCount()) { + out << indent << tag.GetBegin(); + String indent2 = (style & XML_PRETTY) && node[0].IsTag() && node[node.GetCount() - 1].IsTag() ? + indent + '\t' : String(); + for(int i = 0; i < node.GetCount(); i++) + sAsXML(out, node.Node(i), style, indent2); + if(indent2.GetCount()) + out << indent; + out << tag.GetEnd(); + } + else + out << indent << tag(); + } +} + +void AsXML(Stream& out, const XmlNode& n, dword style) +{ + sAsXML(out, n, style, style & XML_PRETTY ? "\r\n" : ""); +} + +String AsXML(const XmlNode& n, dword style) +{ + StringStream ss; + AsXML(ss, n, style); + return ss.GetResult(); +} + +bool AsXMLFile(const char *path, const XmlNode& n, dword style) +{ + FileOut out(path); + if(!out) + return false; + AsXML(out, n, style); + out.Close(); + return !out.IsError(); +} bool IgnoreXmlPaths::DoTag(const String& id) { diff --git a/uppsrc/Core/XML.h b/uppsrc/Core/XML.h index a54312ab7..5d2ab3481 100644 --- a/uppsrc/Core/XML.h +++ b/uppsrc/Core/XML.h @@ -23,6 +23,9 @@ public: String Text(const String& s, byte charset = CHARSET_DEFAULT) { return Text(~s, charset); } String PreservedText(const char *s, byte charset = CHARSET_DEFAULT); String PreservedText(const String& s, byte charset = CHARSET_DEFAULT) { return PreservedText(~s, charset); } + + String GetBegin() const { return tag + '>'; } + String GetEnd() const { return end; } XmlTag& operator()(const char *attr, const char *val); XmlTag& operator()(const char *attr, int q); @@ -250,6 +253,9 @@ public: enum { XML_HEADER = 0x01, XML_DOCTYPE = 0x02, + XML_PRETTY = 0x04, }; -String AsXML(const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE); +void AsXML(Stream& out, const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY); +String AsXML(const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY); +bool AsXMLFile(const char *path, const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY); diff --git a/uppsrc/Core/src.tpp/XmlNode$en-us.tpp b/uppsrc/Core/src.tpp/XmlNode$en-us.tpp index 4a43f2311..7d40eb6b0 100644 --- a/uppsrc/Core/src.tpp/XmlNode$en-us.tpp +++ b/uppsrc/Core/src.tpp/XmlNode$en-us.tpp @@ -228,7 +228,7 @@ is destroyed in operation).&] [s0; &] [s0; &] [s0; &] -[ {{10000@(113.42.0) [s0;%% [*@7;4 XmlNode `- parser and output functions]]}}&] +[ {{10000@(113.42.0) [s0;%% [*@7;4 XmlNode `- parse and output functions]]}}&] [s4;H0; &] [s5;:ParseXML`(XmlParser`&`,dword`): [_^XmlNode^ XmlNode]_[* ParseXML]([_^XmlParser^ XmlPar ser][@(0.0.255) `&]_[*@3 p], [_^dword^ dword]_[*@3 style]_`=_XML`_IGNORE`_DECLS[@(0.0.255) `| @@ -275,17 +275,33 @@ ilter class] to exclude some parts of XML, usually to preserve memory.&] [s3;%% &] [s4; &] +[s5;:AsXML`(Stream`&`,const XmlNode`&`,dword`): [@(0.0.255) void]_[* AsXML]([_^Stream^ Stre +am][@(0.0.255) `&]_[*@3 out], [@(0.0.255) const]_[_^XmlNode^ XmlNode][@(0.0.255) `&]_[*@3 n], + [_^dword^ dword]_[*@3 style]_`=_XML`_HEADER[@(0.0.255) `|]XML`_DOCTYPE[@(0.0.255) `|]XML +`_PRETTY)&] [s5;:AsXML`(const XmlNode`&`,dword`): [_^String^ String]_[* AsXML]([@(0.0.255) const]_[_^XmlNode^ X mlNode][@(0.0.255) `&]_[*@3 n], [_^dword^ dword]_[*@3 style]_`=_XML`_HEADER[@(0.0.255) `|]X -ML`_DOCTYPE)&] +ML`_DOCTYPE[@(0.0.255) `|]XML`_PRETTY)&] +[s5;:AsXMLFile`(const char`*`,const XmlNode`&`,dword`): [@(0.0.255) bool]_[* AsXMLFile]([@(0.0.255) c +onst]_[@(0.0.255) char]_`*[*@3 path], [@(0.0.255) const]_[_^XmlNode^ XmlNode][@(0.0.255) `& +]_[*@3 n], [_^dword^ dword]_[*@3 style]_`=_XML`_HEADER[@(0.0.255) `|]XML`_DOCTYPE[@(0.0.255) `| +]XML`_PRETTY)&] +[s0; &] [s2;%% Creates a XML document from XmlNode [%-*@3 n]. [%-*@3 style] can -be a combination &] +be a combination of&] [s2;%% &] [ {{3581:6419<288;^ [s2;l32; XML`_HEADER] ::= [s2;l64;%% Adds standard XML header at the beginning of the document.] ::^ [s2;l32; XML`_DOCTYPE] ::= [s2;l64;%% Adds DOCTYPE declaration at the beginning of the document with type taken as id of first XML`_TAG sub`-node (which represents -the root element).]}}&] -[s3;%% &] -[s0; ]] \ No newline at end of file +the root element).] +::^ [s2;l32; XML`_PRETTY] +::= [s2;l64;%% XML document is formatted as multiline document with nice +indentation. If not active, everything is in sigle line with +no identantion.]}}&] +[s2; &] +[s2; Output is stored to Stream, returned as String or (with AsXMLFile) +stored to file. AsXMLFile returns true if output file was successfully +created.&] +[s2; ]] \ No newline at end of file diff --git a/uppsrc/Core/src.tpp/XmlParser$en-us.tpp b/uppsrc/Core/src.tpp/XmlParser$en-us.tpp index f47d98ec9..8db2e2a5a 100644 --- a/uppsrc/Core/src.tpp/XmlParser$en-us.tpp +++ b/uppsrc/Core/src.tpp/XmlParser$en-us.tpp @@ -221,6 +221,6 @@ does not make copy of the text).&] [s4; &] [s5;:XmlParser`:`:XmlParser`(Stream`&`): [* XmlParser]([_^Stream^ Stream][@(0.0.255) `&]_[*@3 i n])&] -[s2;%% Creates the parser for xml input stream [%-*@3 in].&] +[s2;%% Creates the parser for the input stream [%-*@3 in].&] [s3;%% &] [s0; ]] \ No newline at end of file