• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "xml_parser.h"
16 #include <algorithm>
17 
18 #include "config_policy_utils.h"
19 
20 namespace OHOS::Rosen {
LoadConfiguration(const char * fileDir)21 int32_t XMLParser::LoadConfiguration(const char* fileDir)
22 {
23     HGM_LOGI("XMLParser opening xml file");
24     xmlDocument_ = xmlReadFile(fileDir, nullptr, 0);
25     if (!xmlDocument_) {
26         HGM_LOGE("XMLParser xmlReadFile failed");
27         return XML_FILE_LOAD_FAIL;
28     }
29 
30     if (!mParsedData_) {
31         mParsedData_ = std::make_unique<PolicyConfigData>();
32     }
33 
34     return EXEC_SUCCESS;
35 }
36 
Parse()37 int32_t XMLParser::Parse()
38 {
39     HGM_LOGD("XMLParser Parse");
40     if (!xmlDocument_) {
41         HGM_LOGE("XMLParser xmlDocument_ is empty, should do LoadConfiguration first");
42         return HGM_ERROR;
43     }
44     xmlNode *root = xmlDocGetRootElement(xmlDocument_);
45     if (root == nullptr) {
46         HGM_LOGE("XMLParser xmlDocGetRootElement failed");
47         return XML_GET_ROOT_FAIL;
48     }
49 
50     if (ParseInternal(*root) == false) {
51         return XML_PARSE_INTERNAL_FAIL;
52     }
53     return EXEC_SUCCESS;
54 }
55 
Destroy()56 void XMLParser::Destroy()
57 {
58     HGM_LOGD("XMLParser Destroying the parser");
59     if (xmlDocument_ != nullptr) {
60         xmlFreeDoc(xmlDocument_);
61         xmlDocument_ = nullptr;
62     }
63 }
64 
GetHgmXmlNodeAsInt(xmlNode & node)65 int32_t XMLParser::GetHgmXmlNodeAsInt(xmlNode &node)
66 {
67     if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Param"))) {
68         return HGM_XML_PARAM;
69     }
70     if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Params"))) {
71         return HGM_XML_PARAMS;
72     }
73     HGM_LOGD("XMLParser failed to identify a xml node : %{public}s", node.name);
74     return HGM_XML_UNDEFINED;
75 }
76 
ParseInternal(xmlNode & node)77 bool XMLParser::ParseInternal(xmlNode &node)
78 {
79     HGM_LOGD("XMLParser parsing an internal node");
80     xmlNode *currNode = &node;
81     if (currNode->xmlChildrenNode == nullptr) {
82         HGM_LOGD("XMLParser stop parsing internal, no children nodes");
83         return false;
84     }
85     currNode = currNode->xmlChildrenNode;
86     int32_t parseSuccess = EXEC_SUCCESS;
87 
88     for (; currNode; currNode = currNode->next) {
89         if (currNode->type != XML_ELEMENT_NODE) {
90             continue;
91         }
92         if (parseSuccess != EXEC_SUCCESS) {
93             return false;
94         }
95         int xmlParamType = GetHgmXmlNodeAsInt(*currNode);
96         if (xmlParamType == HGM_XML_PARAM) {
97             parseSuccess = ParseParam(*currNode);
98         } else if (xmlParamType == HGM_XML_PARAMS) {
99             parseSuccess = ParseParams(*currNode);
100         }
101     }
102     return true;
103 }
104 
ParseParam(xmlNode & node)105 int32_t XMLParser::ParseParam(xmlNode &node)
106 {
107     HGM_LOGI("XMLParser parsing a parameter");
108     if (!mParsedData_) {
109         HGM_LOGE("XMLParser mParsedData_ is not initialized");
110         return HGM_ERROR;
111     }
112 
113     std::string paraName = ExtractPropertyValue("name", node);
114     if (paraName == "default_refreshrate_mode") {
115         HGM_LOGD("XMLParser parsing default_refreshrate_mode");
116         std::string mode = ExtractPropertyValue("value", node);
117         mParsedData_->defaultRefreshRateMode_ = mode;
118 
119         HGM_LOGI("HgmXMLParser ParseParam default_refreshrate_mode %{public}s",
120                  mParsedData_->defaultRefreshRateMode_.c_str());
121     }
122 
123     return EXEC_SUCCESS;
124 }
125 
ParseSubSequentParams(xmlNode & node,std::string & paraName)126 int32_t XMLParser::ParseSubSequentParams(xmlNode &node, std::string &paraName)
127 {
128     int32_t setResult = EXEC_SUCCESS;
129 
130     if (paraName == "additional_touch_rate_config") {
131         ParseAppBufferList(node);
132     } else if (paraName == "refreshRate_strategy_config") {
133         setResult = ParseStrategyConfig(node);
134     } else if (paraName == "refreshRate_virtual_display_config") {
135         if (ExtractPropertyValue("switch", node) == "1") {
136             setResult = ParseSimplex(node, mParsedData_->virtualDisplayConfigs_, "strategy");
137             mParsedData_->virtualDisplaySwitch_ = true;
138         } else {
139             mParsedData_->virtualDisplayConfigs_.clear();
140             mParsedData_->virtualDisplaySwitch_ = false;
141         }
142     } else if (paraName == "safe_vote") {
143         // "1": enable
144         mParsedData_->safeVoteEnabled = ExtractPropertyValue("switch", node) == "1";
145     } else if (paraName == "screen_strategy_config") {
146         setResult = ParseSimplex(node, mParsedData_->screenStrategyConfigs_, "type");
147     } else if (paraName == "screen_config") {
148         setResult = ParseScreenConfig(node);
149     } else if (paraName == "rs_video_frame_rate_vote_config") {
150         setResult = ParseVideoFrameVoteConfig(node);
151     } else if (paraName == "source_tuning_for_yuv420") {
152         setResult = ParseSimplex(node, mParsedData_->sourceTuningConfig_);
153     } else if (paraName == "rs_solid_color_layer_config") {
154         setResult = ParseSimplex(node, mParsedData_->solidLayerConfig_);
155     } else if (paraName == "hfbc_config") {
156         setResult = ParseSimplex(node, mParsedData_->hfbcConfig_);
157     } else {
158         setResult = EXEC_SUCCESS;
159     }
160 
161     return setResult;
162 }
163 
ParseParams(xmlNode & node)164 int32_t XMLParser::ParseParams(xmlNode &node)
165 {
166     std::string paraName = ExtractPropertyValue("name", node);
167     if (paraName.empty()) {
168         return XML_PARSE_INTERNAL_FAIL;
169     }
170     if (!mParsedData_) {
171         HGM_LOGE("XMLParser mParsedData_ is not initialized");
172         return HGM_ERROR;
173     }
174 
175     int32_t setResult = EXEC_SUCCESS;
176     if (paraName == "refresh_rate_4settings") {
177         std::unordered_map<std::string, std::string> refreshRateForSettings;
178         setResult = ParseSimplex(node, refreshRateForSettings);
179         if (setResult != EXEC_SUCCESS) {
180             mParsedData_->xmlCompatibleMode_ = true;
181             setResult = ParseSimplex(node, refreshRateForSettings, "id");
182         }
183         mParsedData_->refreshRateForSettings_.clear();
184         for (auto &[name, id]: refreshRateForSettings) {
185             if (IsNumber(name) && IsNumber(id)) {
186                 mParsedData_->refreshRateForSettings_.emplace_back(
187                     std::pair<int32_t, int32_t>(std::stoi(name), std::stoi(id)));
188             }
189         }
190         std::sort(mParsedData_->refreshRateForSettings_.begin(), mParsedData_->refreshRateForSettings_.end(),
191             [=] (auto rateId0, auto rateId1) { return rateId0.first < rateId1.first; });
192     } else {
193         setResult = ParseSubSequentParams(node, paraName);
194     }
195 
196     if (setResult != EXEC_SUCCESS) {
197         HGM_LOGI("XMLParser failed to ParseParams %{public}s", paraName.c_str());
198     }
199     return EXEC_SUCCESS;
200 }
201 
ParseVideoFrameVoteConfig(xmlNode & node)202 int32_t XMLParser::ParseVideoFrameVoteConfig(xmlNode &node)
203 {
204     mParsedData_->videoFrameRateVoteSwitch_ = ExtractPropertyValue("switch", node) == "1";
205     return ParseSimplex(node, mParsedData_->videoFrameRateList_);
206 }
207 
ParseStrategyConfig(xmlNode & node)208 int32_t XMLParser::ParseStrategyConfig(xmlNode &node)
209 {
210     HGM_LOGD("XMLParser parsing strategyConfig");
211     xmlNode *currNode = &node;
212     if (currNode->xmlChildrenNode == nullptr) {
213         HGM_LOGD("XMLParser stop parsing strategyConfig, no children nodes");
214         return HGM_ERROR;
215     }
216 
217     // re-parse
218     mParsedData_->strategyConfigs_.clear();
219     currNode = currNode->xmlChildrenNode;
220     for (; currNode; currNode = currNode->next) {
221         if (currNode->type != XML_ELEMENT_NODE) {
222             continue;
223         }
224 
225         auto name = ExtractPropertyValue("name", *currNode);
226         auto min = ExtractPropertyValue("min", *currNode);
227         auto max = ExtractPropertyValue("max", *currNode);
228         auto dynamicMode = ExtractPropertyValue("dynamicMode", *currNode);
229         auto isFactor = ExtractPropertyValue("isFactor", *currNode) == "1"; // 1:true, other:false
230         auto drawMin = ExtractPropertyValue("drawMin", *currNode);
231         auto drawMax = ExtractPropertyValue("drawMax", *currNode);
232         auto down = ExtractPropertyValue("down", *currNode);
233         if (!IsNumber(min) || !IsNumber(max) || !IsNumber(dynamicMode)) {
234             return HGM_ERROR;
235         }
236 
237         PolicyConfigData::StrategyConfig strategy;
238         strategy.min = std::stoi(min);
239         strategy.max = std::stoi(max);
240         strategy.dynamicMode = static_cast<DynamicModeType>(std::stoi(dynamicMode));
241         strategy.isFactor = isFactor;
242         strategy.drawMin = IsNumber(drawMin) ? std::stoi(drawMin) : 0;
243         strategy.drawMax = IsNumber(drawMax) ? std::stoi(drawMax) : 0;
244         strategy.down = IsNumber(down) ? std::stoi(down) : strategy.max;
245         ParseBufferStrategyList(*currNode, strategy);
246         mParsedData_->strategyConfigs_[name] = strategy;
247         HGM_LOGI("HgmXMLParser ParseStrategyConfig name=%{public}s min=%{public}d drawMin=%{public}d",
248                  name.c_str(), mParsedData_->strategyConfigs_[name].min, mParsedData_->strategyConfigs_[name].drawMin);
249     }
250 
251     return EXEC_SUCCESS;
252 }
253 
ParseAppBufferList(xmlNode & node)254 void XMLParser::ParseAppBufferList(xmlNode &node)
255 {
256     HGM_LOGD("XMLParser parsing ParseAppBufferList");
257     xmlNode *currNode = &node;
258     if (currNode->xmlChildrenNode == nullptr) {
259         HGM_LOGD("XMLParser stop parsing ParseAppBufferList, no children nodes");
260         return;
261     }
262 
263     mParsedData_->appBufferList_.clear();
264     currNode = currNode->xmlChildrenNode;
265     for (; currNode; currNode = currNode->next) {
266         if (currNode->type != XML_ELEMENT_NODE) {
267             continue;
268         }
269         auto name = ExtractPropertyValue("name", *currNode);
270         mParsedData_->appBufferList_.push_back(name);
271     }
272 }
273 
ParseBufferStrategyList(xmlNode & node,PolicyConfigData::StrategyConfig & strategy)274 void XMLParser::ParseBufferStrategyList(xmlNode &node, PolicyConfigData::StrategyConfig &strategy)
275 {
276     if (mParsedData_->appBufferList_.empty()) {
277         return;
278     }
279     std::unordered_map<std::string, std::string> config;
280     for (auto &name : mParsedData_->appBufferList_) {
281         auto fps = ExtractPropertyValue(name, node);
282         if (IsNumber(fps)) {
283             config.insert(make_pair(name, fps));
284         }
285     }
286     if (config.empty()) {
287         return;
288     }
289     for (auto &it : config) {
290         if (std::stoi(it.second) == 0) {
291             strategy.appBufferBlackList.push_back(it.first);
292         } else {
293             strategy.appBufferList.push_back(make_pair(it.first, std::stoi(it.second)));
294         }
295     }
296     if (strategy.appBufferList.empty()) {
297         return;
298     }
299     std::sort(strategy.appBufferList.begin(), strategy.appBufferList.end(),
300         [](const std::pair<std::string, int32_t>& a, const std::pair<std::string, int32_t>& b) {
301         return a.second > b.second;
302     });
303 
304     return;
305 }
306 
ParseScreenConfig(xmlNode & node)307 int32_t XMLParser::ParseScreenConfig(xmlNode &node)
308 {
309     HGM_LOGD("XMLParser parsing screenConfig");
310     xmlNode *currNode = &node;
311     if (currNode->xmlChildrenNode == nullptr) {
312         HGM_LOGD("XMLParser stop parsing screenConfig, no children nodes");
313         return HGM_ERROR;
314     }
315 
316     auto type = ExtractPropertyValue("type", *currNode);
317     PolicyConfigData::ScreenConfig screenConfig;
318     currNode = currNode->xmlChildrenNode;
319     for (; currNode; currNode = currNode->next) {
320         if (currNode->type != XML_ELEMENT_NODE) {
321             continue;
322         }
323         PolicyConfigData::ScreenSetting screenSetting;
324         auto id = ExtractPropertyValue("id", *currNode);
325         screenSetting.strategy = ExtractPropertyValue("strategy", *currNode);
326         for (xmlNode *thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
327             ParseSubScreenConfig(*thresholdNode, screenSetting);
328         }
329         screenConfig[id] = screenSetting;
330         HGM_LOGI("HgmXMLParser ParseScreenConfig id=%{public}s", id.c_str());
331     }
332     mParsedData_->screenConfigs_[type] = screenConfig;
333     return EXEC_SUCCESS;
334 }
335 
ParseSubScreenConfig(xmlNode & node,PolicyConfigData::ScreenSetting & screenSetting)336 int32_t XMLParser::ParseSubScreenConfig(xmlNode &node, PolicyConfigData::ScreenSetting& screenSetting)
337 {
338     xmlNode *thresholdNode = &node;
339     if (thresholdNode->type != XML_ELEMENT_NODE) {
340         return HGM_ERROR;
341     }
342     auto name = ExtractPropertyValue("name", *thresholdNode);
343     int32_t setResult = EXEC_SUCCESS;
344     if (name == "LTPO_config") {
345         setResult = ParseSimplex(*thresholdNode, screenSetting.ltpoConfig);
346     } else if (name == "property_animation_dynamic_settings") {
347         setResult = ParserDynamicSetting(*thresholdNode, screenSetting.animationDynamicSettings);
348     } else if (name == "ace_scene_dynamic_settings") {
349         setResult = ParserDynamicSetting(*thresholdNode, screenSetting.aceSceneDynamicSettings);
350     } else if (name == "scene_list") {
351         setResult = ParseSceneList(*thresholdNode, screenSetting.sceneList);
352     } else if (name == "game_scene_list") {
353         setResult = ParseSimplex(*thresholdNode, screenSetting.gameSceneList);
354     } else if (name == "anco_scene_list") {
355         setResult = ParseSceneList(*thresholdNode, screenSetting.ancoSceneList);
356     } else if (name == "app_list") {
357         ParseMultiAppStrategy(*thresholdNode, screenSetting);
358     } else if (name == "app_types") {
359         setResult = ParseAppTypes(*thresholdNode, screenSetting.appTypes);
360     } else if (name == "rs_animation_power_config") {
361         setResult = ParseSimplex(*thresholdNode, screenSetting.animationPowerConfig);
362     } else if (name == "ui_power_config") {
363         setResult = ParseSimplex(*thresholdNode, screenSetting.uiPowerConfig);
364     } else {
365         setResult = EXEC_SUCCESS;
366     }
367 
368     if (setResult != EXEC_SUCCESS) {
369         HGM_LOGI("XMLParser failed to ParseScreenConfig %{public}s", name.c_str());
370     }
371     return setResult;
372 }
373 
ParseSimplex(xmlNode & node,std::unordered_map<std::string,std::string> & config,const std::string & valueName,const std::string & keyName)374 int32_t XMLParser::ParseSimplex(xmlNode &node, std::unordered_map<std::string, std::string> &config,
375                                 const std::string &valueName, const std::string &keyName)
376 {
377     HGM_LOGD("XMLParser parsing simplex");
378     xmlNode *currNode = &node;
379     if (currNode->xmlChildrenNode == nullptr) {
380         HGM_LOGD("XMLParser stop parsing simplex, no children nodes");
381         return HGM_ERROR;
382     }
383 
384     // re-parse
385     config.clear();
386     currNode = currNode->xmlChildrenNode;
387     for (; currNode; currNode = currNode->next) {
388         if (currNode->type != XML_ELEMENT_NODE) {
389             continue;
390         }
391 
392         auto key = ExtractPropertyValue(keyName, *currNode);
393         auto value = ExtractPropertyValue(valueName, *currNode);
394         if (key.empty() || value.empty()) {
395             return XML_PARSE_INTERNAL_FAIL;
396         }
397         config[key] = value;
398 
399         HGM_LOGI("HgmXMLParser ParseSimplex %{public}s=%{public}s %{public}s=%{public}s",
400                  keyName.c_str(), key.c_str(), valueName.c_str(), config[key].c_str());
401     }
402 
403     return EXEC_SUCCESS;
404 }
405 
ParserDynamicSetting(xmlNode & node,PolicyConfigData::DynamicSettingMap & dynamicSettingMap)406 int32_t XMLParser::ParserDynamicSetting(xmlNode &node, PolicyConfigData::DynamicSettingMap &dynamicSettingMap)
407 {
408     HGM_LOGD("XMLParser parsing dynamicSetting");
409     xmlNode *currNode = &node;
410     if (currNode->xmlChildrenNode == nullptr) {
411         HGM_LOGD("XMLParser stop parsing dynamicSetting, no children nodes");
412         return HGM_ERROR;
413     }
414 
415     // re-parse
416     dynamicSettingMap.clear();
417     currNode = currNode->xmlChildrenNode;
418     for (; currNode; currNode = currNode->next) {
419         auto dynamicSettingType = ExtractPropertyValue("name", *currNode);
420         PolicyConfigData::DynamicSetting dynamicSetting;
421         dynamicSettingMap[dynamicSettingType] = dynamicSetting;
422         for (xmlNode *thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
423             if (thresholdNode->type != XML_ELEMENT_NODE) {
424                 continue;
425             }
426             auto name = ExtractPropertyValue("name", *thresholdNode);
427             auto min = ExtractPropertyValue("min", *thresholdNode);
428             auto max = ExtractPropertyValue("max", *thresholdNode);
429             auto preferred_fps = ExtractPropertyValue("preferred_fps", *thresholdNode);
430             if (!IsNumber(min) || !IsNumber(max) || !IsNumber(preferred_fps)) {
431                 dynamicSettingMap[dynamicSettingType].clear();
432                 break;
433             }
434             PolicyConfigData::DynamicConfig dynamicConfig;
435             dynamicConfig.min = std::stoi(min);
436             dynamicConfig.max = std::stoi(max);
437             dynamicConfig.preferred_fps = std::stoi(preferred_fps);
438             dynamicSettingMap[dynamicSettingType][name] = dynamicConfig;
439 
440             HGM_LOGI("HgmXMLParser ParserDynamicSetting dynamicType=%{public}s name=%{public}s min=%{public}d",
441                      dynamicSettingType.c_str(), name.c_str(), dynamicSettingMap[dynamicSettingType][name].min);
442         }
443     }
444     return EXEC_SUCCESS;
445 }
446 
ParseSceneList(xmlNode & node,PolicyConfigData::SceneConfigMap & sceneList)447 int32_t XMLParser::ParseSceneList(xmlNode &node, PolicyConfigData::SceneConfigMap &sceneList)
448 {
449     HGM_LOGD("XMLParser parsing sceneList");
450     xmlNode *currNode = &node;
451     if (currNode->xmlChildrenNode == nullptr) {
452         HGM_LOGD("XMLParser stop parsing sceneList, no children nodes");
453         return HGM_ERROR;
454     }
455 
456     // re-parse
457     sceneList.clear();
458     currNode = currNode->xmlChildrenNode;
459     for (; currNode; currNode = currNode->next) {
460         if (currNode->type != XML_ELEMENT_NODE) {
461             continue;
462         }
463         PolicyConfigData::SceneConfig sceneConfig;
464         auto name = ExtractPropertyValue("name", *currNode);
465         sceneConfig.strategy = ExtractPropertyValue("strategy", *currNode);
466         sceneConfig.priority = ExtractPropertyValue("priority", *currNode);
467 
468         sceneList[name] = sceneConfig;
469         HGM_LOGI("HgmXMLParser ParseSceneList name=%{public}s strategy=%{public}s priority=%{public}s",
470                  name.c_str(), sceneList[name].strategy.c_str(), sceneList[name].priority.c_str());
471     }
472 
473     return EXEC_SUCCESS;
474 }
475 
ParseMultiAppStrategy(xmlNode & node,PolicyConfigData::ScreenSetting & screenSetting)476 int32_t XMLParser::ParseMultiAppStrategy(xmlNode &node, PolicyConfigData::ScreenSetting &screenSetting)
477 {
478     auto multiAppStrategy = ExtractPropertyValue("multi_app_strategy", node);
479     if (multiAppStrategy == "focus") {
480         screenSetting.multiAppStrategyType = MultiAppStrategyType::FOLLOW_FOCUS;
481     } else if (multiAppStrategy.find("strategy_") != std::string::npos) {
482         screenSetting.multiAppStrategyType = MultiAppStrategyType::USE_STRATEGY_NUM;
483         screenSetting.multiAppStrategyName = multiAppStrategy.substr(
484             std::string("strategy_").size(), multiAppStrategy.size());
485     } else {
486         screenSetting.multiAppStrategyType = MultiAppStrategyType::USE_MAX;
487     }
488     return ParseSimplex(node, screenSetting.appList, "strategy");
489 }
490 
491 
ParseAppTypes(xmlNode & node,std::unordered_map<int32_t,std::string> & appTypes)492 int32_t XMLParser::ParseAppTypes(xmlNode &node, std::unordered_map<int32_t, std::string> &appTypes)
493 {
494     HGM_LOGD("XMLParser parsing appTypes");
495     xmlNode *currNode = &node;
496     if (currNode->xmlChildrenNode == nullptr) {
497         HGM_LOGD("XMLParser stop parsing appTypes, no children nodes");
498         return HGM_ERROR;
499     }
500 
501     // re-parse
502     appTypes.clear();
503     currNode = currNode->xmlChildrenNode;
504     for (; currNode; currNode = currNode->next) {
505         if (currNode->type != XML_ELEMENT_NODE) {
506             continue;
507         }
508         auto name = ExtractPropertyValue("name", *currNode);
509         if (!IsNumber(name)) {
510             continue;
511         }
512         auto strategy = ExtractPropertyValue("strategy", *currNode);
513         appTypes[std::stoi(name)] = strategy;
514         HGM_LOGI("HgmXMLParser ParseAppTypes name=%{public}s strategy=%{public}s", name.c_str(), strategy.c_str());
515     }
516 
517     return EXEC_SUCCESS;
518 }
519 
ExtractPropertyValue(const std::string & propName,xmlNode & node)520 std::string XMLParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
521 {
522     HGM_LOGD("XMLParser extracting value : %{public}s", propName.c_str());
523     std::string propValue = "";
524     xmlChar *tempValue = nullptr;
525 
526     if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
527         tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
528     }
529 
530     if (tempValue != nullptr) {
531         HGM_LOGD("XMLParser not aempty tempValue");
532         propValue = reinterpret_cast<const char*>(tempValue);
533         xmlFree(tempValue);
534         tempValue = nullptr;
535     }
536 
537     return propValue;
538 }
539 
IsNumber(const std::string & str)540 bool XMLParser::IsNumber(const std::string& str)
541 {
542     if (str.length() == 0) {
543         return false;
544     }
545     auto number = static_cast<uint32_t>(std::count_if(str.begin(), str.end(), [](unsigned char c) {
546         return std::isdigit(c);
547     }));
548     return number == str.length() || (str.compare(0, 1, "-") == 0 && number == str.length() - 1);
549 }
550 
551 } // namespace OHOS::Rosen