@@ -40,10 +40,55 @@ namespace NppXml
4040 }
4141
4242 [[nodiscard]] inline bool loadFileShortcut (Document doc, const wchar_t * filename) {
43- return doc->load_file (filename, pugi::parse_cdata | pugi::parse_escapes | pugi::parse_declaration);
43+ return doc->load_file (filename, pugi::parse_cdata | pugi::parse_escapes | pugi::parse_comments | pugi:: parse_declaration);
4444 }
4545
4646 [[nodiscard]] inline bool saveFileShortcut (Document doc, const wchar_t * filename) {
47+ // Without pugi::parse_eol comments are not eol normalized when loaded.
48+ // To avoid issue with CRLF converting to CRCRLF on save, comments are normalized on save
49+ // to have LF eol.
50+ struct eol_norm_walker : pugi::xml_tree_walker
51+ {
52+ bool for_each (pugi::xml_node& node) override
53+ {
54+ auto normalizeEOL = [](const pugi::string_t & text)
55+ {
56+ pugi::string_t normalized;
57+ const size_t len = text.length ();
58+
59+ for (size_t i = 0 ; i < len; ++i)
60+ {
61+ if (text[i] == PUGIXML_TEXT (' \r ' ))
62+ {
63+ if (i + 1 < len && text[i + 1 ] == PUGIXML_TEXT (' \n ' ))
64+ {
65+ normalized += PUGIXML_TEXT (' \n ' );
66+ ++i;
67+ }
68+ else
69+ {
70+ normalized += PUGIXML_TEXT (' \n ' );
71+ }
72+ }
73+ else
74+ {
75+ normalized += text[i];
76+ }
77+ }
78+ return normalized;
79+ };
80+
81+ if (node.type () == pugi::node_comment)
82+ {
83+ const pugi::string_t normalizedText = normalizeEOL (node.value ());
84+ node.set_value (normalizedText.c_str ());
85+ }
86+ return true ;
87+ }
88+ };
89+
90+ eol_norm_walker walker;
91+ doc->traverse (walker);
4792 return doc->save_file (filename, " " , pugi::format_indent | pugi::format_save_file_text | pugi::format_control_chars_in_hexadecimal);
4893 }
4994
@@ -57,14 +102,14 @@ namespace NppXml
57102
58103 [[nodiscard]] inline Element firstChildElement (const Document& doc, const char * name = nullptr ) {
59104 Node root = doc->root ();
60- return name ? root.find_child ([name](const Element& child) {
61- return std::strcmp (child.name (), name) == 0 ;
105+ return name ? root.find_child ([& name](const Element& child) {
106+ return (child. type () == pugi::node_element) && ( std::strcmp (child.name (), name) == 0 ) ;
62107 }) : root.first_child ();
63108 }
64109
65110 [[nodiscard]] inline Element firstChildElement (const Node& node, const char * name = nullptr ) {
66- return name ? node.find_child ([name](const Element& child) {
67- return std::strcmp (child.name (), name) == 0 ;
111+ return name ? node.find_child ([& name](const Element& child) {
112+ return (child. type () == pugi::node_element) && ( std::strcmp (child.name (), name) == 0 ) ;
68113 }) : node.first_child ();
69114 }
70115
0 commit comments