/** * Copyright (c) 2023 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #include #include "lib/string/ob_sql_string.h" #define private public #include "test_xml_utils.h" #include "lib/xml/ob_xpath.h" #include "lib/xml/ob_path_parser.h" #include "lib/allocator/ob_mod_define.h" #include "lib/allocator/page_arena.h" #include "lib/xml/ob_xml_parser.h" #include "libxml2/libxml/xmlmemory.h" #include "lib/xml/ob_xml_util.h" #undef private using namespace oceanbase::common; using namespace ObXmlTestUtils; class TestXPath : public ::testing::Test { public: TestXPath() {} ~TestXPath() {} virtual void SetUp() {} virtual void TearDown() {} static void SetUpTestCase() {} static void TearDownTestCase() {} private: // disallow copy DISALLOW_COPY_AND_ASSIGN(TestXPath); }; ObString axis_path_map[30][2] = { {"/self::abc","/self::abc"}, {"/parent::a","/parent::a"}, {"/ancestor::a1","/ancestor::a1"}, {"/ancestor-or-self::a1","/ancestor-or-self::a1"}, {"/child::a1","/a1"}, {"/ancestor::_a1","/ancestor::_a1"}, {"/descendant::a_2","/descendant::a_2"}, {"/descendant-or-self::a1","/descendant-or-self::a1"}, {"/following-sibling::a1","/following-sibling::a1"}, {"/following::a1","/following::a1"}, //10 {"/preceding-sibling::a1","/preceding-sibling::a1"}, {"/preceding::k","/preceding::k"}, {"/attribute::k","/@k"}, {"/@k","/@k"}, {"/namespace::k","/namespace::k"}, // 15 {"/self","/self"}, {"/parent","/parent"}, {"/ancestor","/ancestor"}, {"/ancestor-or-self","/ancestor-or-self"}, {"/child","/child"}, {"/child::ancestor","/ancestor"}, {"/descendant","/descendant"}, {"/descendant-or-self","/descendant-or-self"}, {"/following-sibling","/following-sibling"}, {"/following","/following"}, //25 {"/preceding-sibling","/preceding-sibling"}, {"/preceding","/preceding"}, {"/attribute","/attribute"}, {"/a/preceding-sibling","/a/preceding-sibling"}, {"/namespace","/namespace"}, //30 }; TEST_F(TestXPath, test_axis) { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); std::cout<<"------begin axis test------"< (allocator.alloc(sizeof(ObDatum))); if (OB_ISNULL(data)) { ret = OB_BAD_NULL_ERROR; } else { data = new (data) ObDatum(); data->set_string(data_value); for (int i = 0; i < 15 && OB_SUCC(ret); ++i) { ret = ans.add(ns_str[i], data); } std::cout<<"------begin ns test------"< 3]","/a[last() > 3]"}, {"/a[true()]", "/a[true()]"}, {"a[false()]", "/a[false()]"}, {"/a[boolean(/a)]", "/a[boolean(/a)]"}, // 10 {"a[not(a)]", "/a[not(a)]"} }; TEST_F(TestXPath, test_parse_good_func) { int ret = OB_SUCCESS; ObString default_ns; ObArenaAllocator allocator(ObModIds::TEST); ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); std::cout<<"------begin tag test------"< 20","12 > 20"}, {"12 >= 20","12 >= 20"}, {"1 or 0","1 or 0"}, {"1 and 0","1 and 0"}, //10 {".5 + .6","0.5 + 0.6"}, {"-1 + -1.5","-1 + -1.5"}, {"-2.5 --0.5", "-2.5 - -0.5"}, {"-2.5 ---0.5", "-2.5 - 0.5"}, {"-2.5 + 0.5 * 1", "-2.5 + 0.5 * 1"}, {"-2.5 + 0.5 div 1", "-2.5 + 0.5 div 1"}, {"-2.5 - ---0.5 div 1 and 1 + 1", "-2.5 - -0.5 div 1 and 1 + 1"}, {"/abc[position() >= 1][last() <= 10] ", "/abc[position() >= 1][last() <= 10]"}, {"/abc[position() >= 1][last() <= 10][1 and 1<2] ", "/abc[position() >= 1][last() <= 10][1 and 1 < 2]"}, {"/abc[1+1 | 1-1]","/abc[1 + 1 | 1 - 1]" }, // 20 {"/abc | /efg", "/abc | /efg"}, {"/abc | /de |/fg", "/abc | /de | /fg"}, {"/Grade/Format/list_Step", "/Grade/Format/list_Step"}, // user path {"@G_SORT", "@G_SORT"}, {"/Grade/Format/list_Step[text()=\"' || B.GRADE || '\"]/@PD", "/Grade/Format/list_Step[text() = \"' || B.GRADE || '\"]/@PD"}, {"abc + abc", "abc + abc"}, {"\"abc\" > \"abc\"", "\"abc\" > \"abc\""}, {"count(/abc) + count(/abc)", "count(/abc) + count(/abc)"}, {"count(/abc) > count(/abc)", "count(/abc) > count(/abc)"}, {"1 or 1 < 2", "1 or 1 < 2"}, // 30 {"/abc[abc > abc]", "/abc[abc > abc]"}, {"/abc[1]", "/abc[1]"}, {"/Grade/Format/list_Step[text()=\"' || A.GRADE || '\"]/@PD", "/Grade/Format/list_Step[text() = \"' || A.GRADE || '\"]/@PD"}, {"/Page/DataSources/*[ID=\"' || datasource_id_ || '\"]", "/Page/DataSources/*[ID = \"' || datasource_id_ || '\"]"}, {"/Page/*/*/Group/Elements/Element[@id=\"' || s_element_id_ || '\"]", "/Page/*/*/Group/Elements/Element[@id = \"' || s_element_id_ || '\"]"}, {"/Page/DataSources/DataSource[@id=\"' || s_data_source_id_ || '\"]","/Page/DataSources/DataSource[@id = \"' || s_data_source_id_ || '\"]"} //36 }; TEST_F(TestXPath, test_parse_good_filter) { int ret = OB_SUCCESS; ObString default_ns; ObArenaAllocator allocator(ObModIds::TEST); ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); std::cout<<"------begin tag test------"<Learning XML-first", "Learning XML-last"}; TEST_F(TestXPath, test_seek_element_by_tag) // tested { // 用于解析 ObString str0 = "bookstore/book/title"; ObString xml_text("Learning XML-firstLearning XML-last"); int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); ObXmlBin xbin(ctx); ASSERT_EQ(xbin.parse_tree(doc), 0); // 用于解析 std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_element[i]); std::cout<print(buf,true); ObString s(buf.ptr()); ASSERT_EQ(s, seek_element[i]); std::cout<roottest1test_start" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "test_endtest2"); int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); ObXmlBin xbin(ctx); ASSERT_EQ(xbin.parse_tree(doc), 0); // 用于解析 std::cout<node_to_string(buf); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<"); int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); ObXmlBin xbin(ctx); ASSERT_EQ(xbin.parse_tree(doc), 0); // 用于解析 std::cout<node_to_string(buf); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<bbb1bbb2"); int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); ObXmlBin xbin(ctx); ASSERT_EQ(xbin.parse_tree(doc), 0); // 用于解析 std::cout<node_to_string(buf); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<99"}; TEST_F(TestXPath, test_seek_suite_filter) // tested { // 用于解析 ObString str0 = "s/a99[//text() > \"离开\"]"; ObString xml_text("离开景圆圆99"); int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); ObXmlBin xbin(ctx); ASSERT_EQ(xbin.parse_tree(doc), 0); // 用于解析 std::cout<node_to_string(buf); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<-100", "+2.33"}; TEST_F(TestXPath, test_seek_suite_complex_filter) // tested { // 用于解析 ObString str0 = "/a[//text() >= -100]/node()[./node() < 3]"; ObString xml_text("aaa-100+2.33"); int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); ObXmlBin xbin(ctx); ASSERT_EQ(xbin.parse_tree(doc), 0); // 用于比较 std::cout<node_to_string(buf); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<bbb"); int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); ObXmlBin xbin(ctx); ASSERT_EQ(xbin.parse_tree(doc), 0); // 用于解析 std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); //ASSERT_EQ(s, seek_descendant_or_self_text[i]); std::cout<print(buf,true); ObString s(buf.ptr()); //ASSERT_EQ(s, seek_descendant_or_self_text[i]); std::cout<Learning XML-first", "Learning XML-last"}; TEST_F(TestXPath, test_seek_all_element) // tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("Learning XML-firstLearning XML-last"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "bookstore/book/*"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_all_element[i]); std::cout<test2"}; TEST_F(TestXPath, test_seek_ns_element) // to test { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("test1test2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "bookstore/a:book"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_ns_element[i]); std::cout<test1"}; TEST_F(TestXPath, test_seek_root) // tested { int ret = OB_SUCCESS; ObCollationType type = CS_TYPE_UTF8MB4_GENERAL_CI; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("test1"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "/"; std::cout<node_to_string(buf); std::cout<(res); xnode->print_document(buf_str, type, ObXmlFormatType::NO_FORMAT); ObString s(buf_str.ptr()); ASSERT_EQ(s, seek_root[i]); std::cout<"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); ObString default_ns; ObPathVarObject pass(allocator); ObDatum data; data.set_string("bbb"); ret = pass.add("a", &data); ASSERT_EQ(OB_SUCCESS, ret); ObPathExprIter pathiter(&allocator); pathiter.init(ctx,str0, default_ns, doc, &pass); // 解析 ret = pathiter.open(); ASSERT_EQ(OB_SUCCESS, ret); // to_string ObJsonBuffer buf(&allocator); ret = pathiter.path_node_->node_to_string(buf); std::cout<print(buf,true); ObString s(buf.ptr()); ASSERT_EQ(s, seek_all_attribute[i]); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_all_attribute[i]); std::cout<"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); ObString default_ns; ObPathVarObject pass(allocator); ObDatum data; data.set_string("bbb"); ret = pass.add("a", &data); ASSERT_EQ(OB_SUCCESS, ret); ObPathExprIter pathiter(&allocator); pathiter.init(ctx,str0, default_ns, doc, &pass); // 解析 ret = pathiter.open(); ASSERT_EQ(OB_SUCCESS, ret); // to_string ObJsonBuffer buf(&allocator); ret = pathiter.path_node_->node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); std::string tmp_s(s.ptr(), s.length()); std::string tmp_seek(seek_certain_attribute[i].ptr(), seek_certain_attribute[i].length()); ASSERT_EQ(tmp_s, tmp_seek); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "bookstore/book/@a:lang"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_ns_attribute[i]); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<book1", "", "", "book2"}; TEST_F(TestXPath, test_seek_node) // tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("abcbook1book2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "bookstore/node()"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_node[i]); std::cout<book1book2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "bookstore/book/text()"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_text[i]); std::cout<", ""}; TEST_F(TestXPath, test_seek_comment) // tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("book1book2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "bookstore/comment()"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); std::cout<", ""}; TEST_F(TestXPath, test_seek_pi_wildcard) // tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("book1book2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "bookstore/processing-instruction()"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_pi_wildcard[i]); std::cout<"}; TEST_F(TestXPath, test_seek_certain_pi) // tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("book1book2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "bookstore/processing-instruction(\"price2\")"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_certain_pi[i]); std::cout<bbb1bbb2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "/a/h:b/@b1"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_default_ns_attribute[i]); std::cout<b1b11b12", "b2b21b22", "b3b31b32"}; TEST_F(TestXPath, test_seek_self) { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "/root/*/b/*/self::*"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_self[i]); std::cout<b11", "b12"}; TEST_F(TestXPath, test_seek_basic_descendant) // tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 // '/descendant::node()/*' ObString str0 = "root/*/b/b1/descendant::*"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_basic_descendant[i]); std::cout<roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 // root/*/b/descendant::*/node()/text() ObString str0 = "root/*/b/descendant::*/node()/text()"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); ASSERT_EQ(s, seek_descendant[i]); std::cout<roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "root/*/b/descendant-or-self::*/node()/text()"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); std::cout<roottest1test_start" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "test_endtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "/descendant-or-self::node()/text()"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); std::cout<" "AAA" ""}; TEST_F(TestXPath, test_seek_user_extract) { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("" "" "AAA" "" ""); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "/Rule/Format"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); std::cout<b2b21b22"}; TEST_F(TestXPath, test_seek_parent) // tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "root/*/b/b2/b22/parent::*"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<b21", "b22"}; TEST_F(TestXPath, test_seek_parent_child) // tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "root/*/b/b2/b22/parent::*/node()"; std::cout<node_to_string(buf); std::cout<(res); writer.visit(xnode); ObString s = writer.get_xml_text(); std::cout<roottest1aa1a2a3bb1b11b12b2b21b22b3b31b32cc1c2c3testtest2", "aa1a2a3bb1b11b12b2b21b22b3b31b32cc1c2c3", "bb1b11b12b2b21b22b3b31b32", "b2b21b22"}; TEST_F(TestXPath, test_seek_ancestor) // tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "root/*/b/b2/b22/ancestor::*"; std::cout<node_to_string(buf); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<roottest1aa1a2a3bb1b11b12b2b21b22b3b31b32cc1c2c3testtest2", "aa1a2a3bb1b11b12b2b21b22b3b31b32cc1c2c3", "bb1b11b12b2b21b22b3b31b32", "b2b21b22"}; TEST_F(TestXPath, test_seek_ancestor_or_self) //tested { int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObString xml_text("roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "root/*/b/b2/b22/ancestor::*"; std::cout<node_to_string(buf); std::cout<print(buf,true); ObString s(buf.ptr()); std::cout<roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "root/ancestor::*"; std::cout<node_to_string(buf); std::cout<roottest1" "aa1a2a3" "bb1b11b12" "b2b21b22" "b3b31b32" "cc1c2c3" "testtest2"); ObXmlDocument* doc = nullptr; ObMulModeMemCtx* ctx = nullptr; ASSERT_EQ(ObXmlUtil::create_mulmode_tree_context(&allocator, ctx), OB_SUCCESS); ret = ObXmlParserUtils::parse_document_text(ctx, xml_text, doc); ASSERT_EQ(OB_SUCCESS, ret); // 用于解析 ObString str0 = "root/parent::*"; std::cout<node_to_string(buf); std::cout<