diff --git a/static_core/plugins/ets/sdk/api/@ohos.xml.ets b/static_core/plugins/ets/sdk/api/@ohos.xml.ets index 2312da897a701f2a5d9b8863dd5753a18c8cf810..4223109b2b61a48826c5b0f6c13b58723354f93f 100644 --- a/static_core/plugins/ets/sdk/api/@ohos.xml.ets +++ b/static_core/plugins/ets/sdk/api/@ohos.xml.ets @@ -32,6 +32,8 @@ function createBusinessError(code: int, message: string) { export namespace xml { + export type AttributeWithTagCb = (tagName: string, key: string, value: string) => boolean + export enum EventType { START_DOCUMENT, END_DOCUMENT, @@ -89,6 +91,7 @@ export namespace xml { supportDoctype?: boolean tagValueCallbackFunction?: (name: string, value: string) => boolean tokenValueCallbackFunction?: (eventType: EventType, value: ParseInfo) => boolean + attributeWithTagCallbackFunction?: AttributeWithTagCb } export class XmlPullParser { @@ -544,7 +547,8 @@ export namespace xml { option.supportDoctype ?? false, option.attributeValueCallbackFunction, option.tagValueCallbackFunction, - option.tokenValueCallbackFunction + option.tokenValueCallbackFunction, + option.attributeWithTagCallbackFunction ); } @@ -555,7 +559,8 @@ export namespace xml { supportDoctype: boolean, attributeValueCallbackFunction?: (name: string, value: string) => boolean, tagValueCallbackFunction?: (name: string, value: string) => boolean, - tokenValueCallbackFunction?: (eventType: EventType, value: ParseInfo) => boolean + tokenValueCallbackFunction?: (eventType: EventType, value: ParseInfo) => boolean, + attributeWithTagCallbackFunction?: AttributeWithTagCb ): boolean; private static native parserErrorInfo(pointer: long): string; diff --git a/static_core/plugins/ets/sdk/native/api/ani_xmlpullparser.cpp b/static_core/plugins/ets/sdk/native/api/ani_xmlpullparser.cpp index 30c8dfb2f5d7726efc4e63543dcb91dddbf6d5ad..4cebd2b63a778d2d4c76347cce4308dcb69ee693 100644 --- a/static_core/plugins/ets/sdk/native/api/ani_xmlpullparser.cpp +++ b/static_core/plugins/ets/sdk/native/api/ani_xmlpullparser.cpp @@ -160,7 +160,7 @@ XmlPullParser::~XmlPullParser() // CC-OFFNXT(G.FUN.01-CPP) options of parse ani_boolean XmlPullParser::ParseXml(ani_env *env, [[maybe_unused]] ani_class self, ani_long pointer, ani_boolean ignoreNS, ani_boolean supportDCT, ani_fn_object attrValCb, - ani_fn_object tagValCb, ani_fn_object tknCalCb) + ani_fn_object tagValCb, ani_fn_object tknCalCb, ani_fn_object attrTagCb) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) CHECK_NON_NULL_PARSER_AND_RETURN(pointer, false); @@ -170,6 +170,7 @@ ani_boolean XmlPullParser::ParseXml(ani_env *env, [[maybe_unused]] ani_class sel that->attrFunc_ = attrValCb; that->tagFunc_ = tagValCb; that->tokenFunc_ = tknCalCb; + that->attrWithTagFunc_ = attrTagCb; that->Parse(env); return static_cast(that->xmlPullParserError_.empty()); } @@ -266,14 +267,23 @@ bool XmlPullParser::ParseToken(ani_env *env) const return static_cast(UnboxToBoolean(env, static_cast(returnVal))); } -bool XmlPullParser::ParseAttr(ani_env *env) const +bool XmlPullParser::ParseAttr(ani_env *env, ani_fn_object attriFun) const { for (size_t i = 0; i < attrCount_; ++i) { ani_string key = CreateStringUtf8(env, attributes_[i * 4 + 2]); // 4 and 2: number of args ani_string value = CreateStringUtf8(env, attributes_[i * 4 + 3]); // 4 and 3: number of args - std::vector argv {key, value}; ani_ref returnVal {}; - env->FunctionalObject_Call(attrFunc_, argv.size(), argv.data(), &returnVal); + std::vector argv {}; + if (attriFun == attrFunc_) { + argv.push_back(key); + argv.push_back(value); + } else { + ani_string tagName = CreateStringUtf8(env, name_); + argv.push_back(tagName); + argv.push_back(key); + argv.push_back(value); + } + env->FunctionalObject_Call(attriFun, argv.size(), argv.data(), &returnVal); if (!static_cast(UnboxToBoolean(env, static_cast(returnVal)))) { return false; } @@ -298,6 +308,16 @@ bool XmlPullParser::HandleTokenFunc(ani_env *env) return ParseToken(env); } +bool XmlPullParser::HandleAttrWithTagFunc(ani_env *env) +{ + if (!(attrWithTagFunc_ && attrCount_)) { + return true; + } + bool bRec = ParseAttr(env, attrWithTagFunc_); + attrCount_ = 0; + return bRec; +} + /** * This function will be deprecated in the future due to a bug. * After parsing the data, since the variable attrCount_ was reset to 0, @@ -308,7 +328,7 @@ bool XmlPullParser::HandleAttrFunc(ani_env *env) if (IsNullishValue(env, static_cast(attrFunc_)) || attrCount_ == 0U) { return true; } - bool bRec = ParseAttr(env); + bool bRec = ParseAttr(env, attrFunc_); attrCount_ = 0; return bRec; } @@ -318,7 +338,8 @@ void XmlPullParser::Parse(ani_env *env) bool tagFuncIsNull = IsNullishValue(env, static_cast(tagFunc_)); bool attrFuncIsNull = IsNullishValue(env, static_cast(attrFunc_)); bool tokenFuncIsNull = IsNullishValue(env, static_cast(tokenFunc_)); - if (tagFuncIsNull && attrFuncIsNull && tokenFuncIsNull) { + bool attrTagFuncIsNull = IsNullishValue(env, static_cast(attrWithTagFunc_)); + if (tagFuncIsNull && attrFuncIsNull && tokenFuncIsNull && attrTagFuncIsNull) { return; } while (type_ != TagEnum::END_DOCUMENT) { @@ -331,6 +352,9 @@ void XmlPullParser::Parse(ani_env *env) if (!tokenFuncIsNull && !HandleTokenFunc(env)) { break; } + if (!attrTagFuncIsNull && !HandleAttrWithTagFunc(env)) { + break; + } if (!attrFuncIsNull && !HandleAttrFunc(env)) { break; } diff --git a/static_core/plugins/ets/sdk/native/api/ani_xmlpullparser.h b/static_core/plugins/ets/sdk/native/api/ani_xmlpullparser.h index 2d5c53a803374aea6e5bfb3e3a0c64a9226143ab..5e0aa31ae4ae08afe055e473a4745a4c2834cc5a 100644 --- a/static_core/plugins/ets/sdk/native/api/ani_xmlpullparser.h +++ b/static_core/plugins/ets/sdk/native/api/ani_xmlpullparser.h @@ -53,9 +53,9 @@ public: static ani_long BindNative(ani_env *env, ani_class self, ani_string content); static ani_boolean ReleaseNative(ani_env *env, ani_class self, ani_long pointer); // CC-OFFNXT(G.FUN.01-CPP) options of parse - static ani_boolean ParseXml(ani_env *env, ani_class self, ani_long pointer, ani_boolean ignoreNS, + static ani_boolean ParseXml(ani_env *env, [[maybe_unused]] ani_class self, ani_long pointer, ani_boolean ignoreNS, ani_boolean supportDCT, ani_fn_object attrValCb, ani_fn_object tagValCb, - ani_fn_object tknCalCb); + ani_fn_object tknCalCb, ani_fn_object attrTagCb); static ani_ref GetParseError(ani_env *env, ani_class self, ani_long pointer); private: @@ -153,10 +153,11 @@ private: void ParseCdect(); bool ParseTag(ani_env *env) const; - bool ParseAttr(ani_env *env) const; + bool ParseAttr(ani_env *env, ani_fn_object attriFun) const; bool ParseToken(ani_env *env) const; bool HandleTagFunc(ani_env *env); bool HandleTokenFunc(ani_env *env); + bool HandleAttrWithTagFunc(ani_env *env); bool HandleAttrFunc(ani_env *env); void ParseNspFunction(); @@ -182,6 +183,7 @@ private: ani_fn_object tagFunc_ {nullptr}; ani_fn_object attrFunc_ {nullptr}; ani_fn_object tokenFunc_ {nullptr}; + ani_fn_object attrWithTagFunc_ {nullptr}; std::string strXml_ {}; std::string prefix_ {}; diff --git a/static_core/plugins/ets/sdk/native/main.cpp b/static_core/plugins/ets/sdk/native/main.cpp index c4fcc8ce75dc0fd23e0529af0faf78732de56b3a..dffc33d9be274c659c5b901de4de9f5cb8e6a100 100644 --- a/static_core/plugins/ets/sdk/native/main.cpp +++ b/static_core/plugins/ets/sdk/native/main.cpp @@ -293,7 +293,9 @@ static ani_status BindXmlPullParser(ani_env *env) std::array methods = { ani_native_function {"bindNative", "C{std.core.String}:l", reinterpret_cast(XmlPullParser::BindNative)}, ani_native_function {"releaseNative", "l:z", reinterpret_cast(XmlPullParser::ReleaseNative)}, - ani_native_function {"parseXmlInner", "lzzC{std.core.Function2}C{std.core.Function2}C{std.core.Function2}:z", + ani_native_function {"parseXmlInner", + "lzzC{std.core.Function2}C{std.core.Function2}C{std.core.Function2}\ + C{std.core.Function3}:z", reinterpret_cast(XmlPullParser::ParseXml)}, ani_native_function {"parserErrorInfo", "l:C{std.core.String}", reinterpret_cast(XmlPullParser::GetParseError)}, diff --git a/static_core/plugins/ets/tests/ets_sdk/api/@ohos/xml/XmlPullParserTest2.ets b/static_core/plugins/ets/tests/ets_sdk/api/@ohos/xml/XmlPullParserTest2.ets index 59b8a2795e89873b6c5ecaa333635eb9cb59b283..954778a99332476685c590abc017016fa6022376 100644 --- a/static_core/plugins/ets/tests/ets_sdk/api/@ohos/xml/XmlPullParserTest2.ets +++ b/static_core/plugins/ets/tests/ets_sdk/api/@ohos/xml/XmlPullParserTest2.ets @@ -13,9 +13,11 @@ * limitations under the License. */ import {xml} from "@ohos.xml" +import {util} from "@ohos.util" function main(): int { const suite = new arktest.ArkTestsuite("XmlPullParser API tests, part2"); + suite.addTest("Testing XML PullParser with attributeWithTagCallbackFunction as function.", testXmlPullParserParseOptions0010) suite.addTest("Testing XML PullParser with tokenValueCallbackFunction as undefined.", testXmlPullParserParseOptions0009) suite.addTest("Testing XML PullParser with tokenValueCallbackFunction as function.", testXmlPullParserParseOptions0008) suite.addTest("Testing XML PullParser with tagValueCallbackFunction as function.", testXmlPullParserParseOptions0006) @@ -478,3 +480,29 @@ function testXmlPullParserParseOptions0009() { } } +function testXmlPullParserParseOptions0010() { + console.log("orange: test start"); + let xmlStr = + '' + + '' + + '' + + ''; + let textEncoder = new util.TextEncoder(); + let arrBuffer = textEncoder.encodeInto(xmlStr); + let that = new xml.XmlPullParser(arrBuffer.buffer as object as ArrayBuffer, 'UTF-8'); + + let attrWithTag = (tagName: string, key: string, value: string): boolean => { + if (tagName == "orange") { + console.log("value = " + value); + } + return true; + } + + let options: xml.ParseOptions = { + supportDoctype: true, + ignoreNameSpace: true, + attributeWithTagCallbackFunction:attrWithTag + }; + that.parseXml(options); +} +