1%%%------------------------------------------------------------------- 2%%% File : xpath_abbrev.erl 3%%% Author : Bertil Karlsson <bertil@finrod> 4%%% Description : 5%%% 6%%% Created : 17 Jan 2006 by Bertil Karlsson <bertil@finrod> 7%%%------------------------------------------------------------------- 8-module(xpath_abbrev). 9 10-export([test/0, check_node_set/2, ticket_6873/0, ticket_7496/0, functions/0]). 11-export([namespaces/0]). 12 13-include_lib("common_test/include/ct.hrl"). 14-include_lib("xmerl/include/xmerl.hrl"). 15 16test() -> 17 {E,_} = xmerl_scan:file("xpath.xml"), 18 19 Res1 = xmerl_xpath:string("blipp",E), 20 ok = check_node_set("blipp",Res1), 21 Res2 = xmerl_xpath:string("*",E), 22 ok = check_node_set("*",Res2), 23 Res3 = xmerl_xpath:string("blipp/blupp/plopp/text()",E), 24 ok = check_node_set("blipp/blupp/plopp/text()",Res3), 25 Res4 = xmerl_xpath:string("blipp/blupp/@att2",E), 26 ok = check_node_set("blipp/blupp/@att2",Res4), 27 Res5 = xmerl_xpath:string("blipp/@*",E), 28 ok = check_node_set("blipp/@*",Res5), 29 Res6 = xmerl_xpath:string("blipp[2]",E), 30 ok = check_node_set("blipp[2]",Res6), 31 Res7 = xmerl_xpath:string("blipp[last()]",E), 32 ok = check_node_set("blipp[last()]",Res7), 33 Res8 = xmerl_xpath:string("*/blupp",E), 34 ok = check_node_set("*/blupp",Res8), 35 Res9 = xmerl_xpath:string("/myBS_model/blipp[3]/blupp[2]",E), 36 ok = check_node_set("/myBS_model/blipp[3]/blupp[2]",Res9), 37 Res10 = xmerl_xpath:string("blipp//plopp",E), 38 ok = check_node_set("blipp//plopp",Res10), 39 Res11 = xmerl_xpath:string("//plopp",E), 40 ok = check_node_set("//plopp",Res11), 41 Res12 = xmerl_xpath:string("//blupp/plopp",E), 42 ok = check_node_set("//blupp/plopp",Res12), 43 Res13 = xmerl_xpath:string(".",E), 44 ok = check_node_set(".",Res13), 45 Res14 = xmerl_xpath:string(".//blipp2",E), 46 ok = check_node_set(".//blipp2",Res14), 47 Res15 = xmerl_xpath:string(".//blipp2/blupp/plopp/..",E), 48 ok = check_node_set(".//blipp2/blupp/plopp/..",Res15), 49 Res16 = xmerl_xpath:string(".//blipp[2]/blupp/plopp/../@att2",E), 50 ok = check_node_set(".//blipp[2]/blupp/plopp/../@att2",Res16), 51 Res17 = xmerl_xpath:string(".//blipp/blupp/plopp[2]/../@att2",E), 52 ok = check_node_set(".//blipp/blupp/plopp[2]/../@att2",Res17), 53 Res18 = xmerl_xpath:string("blipp[@id='name2']",E), 54 ok = check_node_set("blipp[@id='name2']",Res18), 55 Res19 = xmerl_xpath:string("blipp[@id='name2'][3]",E), 56 ok = check_node_set("blipp[@id='name2'][3]",Res19), 57 Res20 = xmerl_xpath:string("//blupp[plopp=\"here are some more text\"]",E), 58 ok = check_node_set("//blupp[plopp=\"here are some more text\"]",Res20), 59 Res21 = xmerl_xpath:string("//blupp[plopp]",E), 60 ok = check_node_set("//blupp[plopp]",Res21), 61 Res22 = xmerl_xpath:string("blipp[@id and @test]",E), 62 ok = check_node_set("blipp[@id and @test]",Res22). 63 64check_node_set("blipp",[E1,E2,E3]) -> 65 ok = xml_element_name(E1,blipp), 66 ok = xml_element_name(E2,blipp), 67 ok = xml_element_name(E3,blipp), 68 ok; 69check_node_set("*",[E1,E2,E3,E4]) -> 70 ok = xml_element_name(E1,blipp), 71 ok = xml_element_name(E2,blipp), 72 ok = xml_element_name(E3,blipp), 73 ok = xml_element_name(E4,blipp2), 74 ok; 75check_node_set("blipp/blupp/plopp/text()",[T1,T2]) -> 76 #xmlText{value="here are some text"} = T1, 77 #xmlText{value="here are some more text"} = T2, 78 ok; 79check_node_set("blipp/blupp/@att2",[A1,A2]) -> 80 #xmlAttribute{name=att2} = A1, 81 #xmlAttribute{name=att2} = A2, 82 ok; 83check_node_set("blipp/@*",[A1,A2,A3,A4]) -> 84 #xmlAttribute{} = A1, 85 #xmlAttribute{} = A2, 86 #xmlAttribute{} = A3, 87 #xmlAttribute{} = A4, 88 ok; 89check_node_set("blipp[2]",[E]) -> 90 #xmlElement{name=blipp, 91 attributes=[#xmlAttribute{name=id,value="name2"}]} = E, 92 ok; 93check_node_set("blipp[last()]",[E]) -> 94 #xmlElement{name=blipp, 95 attributes=[#xmlAttribute{name=id,value="name3"}|_]} = E, 96 ok; 97check_node_set("*/blupp",[E1,E2,E3,E4,E5,E6]) -> 98 ok = xml_element_name(E1,blupp), 99 ok = xml_element_name(E2,blupp), 100 ok = xml_element_name(E3,blupp), 101 ok = xml_element_name(E4,blupp), 102 ok = xml_element_name(E5,blupp), 103 ok = xml_element_name(E6,blupp), 104 ok; 105check_node_set("/myBS_model/blipp[3]/blupp[2]",[E]) -> 106 #xmlElement{name=blupp, 107 attributes=[#xmlAttribute{name=att,value="bluppc2"}]}=E, 108 ok; 109check_node_set("blipp//plopp",[#xmlElement{name=plopp},#xmlElement{name=plopp}]) -> 110 ok; 111check_node_set("//plopp",[E1,E2,E3]) -> 112 ok = xml_element_name(E1,plopp), 113 ok = xml_element_name(E2,plopp), 114 ok = xml_element_name(E3,plopp), 115 ok; 116check_node_set("//blupp/plopp",[E1,E2,E3]) -> 117 ok = xml_element_name(E1,plopp), 118 ok = xml_element_name(E2,plopp), 119 ok = xml_element_name(E3,plopp), 120 ok; 121check_node_set(".",[#xmlElement{name=myBS_model}]) -> 122 ok; 123check_node_set(".//blipp2",[#xmlElement{name=blipp2}]) -> 124 ok; 125check_node_set(".//blipp2/blupp/plopp/..",[#xmlElement{name=blupp}]) -> 126 ok; 127check_node_set(".//blipp[2]/blupp/plopp/../@att2",[#xmlAttribute{name=att2,value="bluppb"}]) -> 128 ok; 129check_node_set(".//blipp/blupp/plopp[2]/../@att2",[#xmlAttribute{name=att2,value="bluppc"}]) -> 130 ok; 131check_node_set("blipp[@id='name2']",[E]) -> 132 #xmlElement{name=blipp, 133 attributes=[#xmlAttribute{name=id,value="name2"}]}=E, 134 ok; 135check_node_set("blipp[@id='name2'][3]",[]) -> 136 ok; 137check_node_set("//blupp[plopp=\"here are some more text\"]",[E]) -> 138 #xmlElement{name=blupp, 139 content=[_T,#xmlElement{name=plopp,content=C}|_]} = E, 140 true = lists:keymember("here are some more text",#xmlText.value,C), 141 ok; 142check_node_set("//blupp[plopp]",[E1,E2,E3]) -> 143 #xmlElement{name=blupp, 144 content=C1} = E1, 145 true = lists:keymember(plopp,#xmlElement.name,C1), 146 #xmlElement{name=blupp, 147 content=C2} = E2, 148 true = lists:keymember(plopp,#xmlElement.name,C2), 149 #xmlElement{name=blupp, 150 content=C3} = E3, 151 true = lists:keymember(plopp,#xmlElement.name,C3), 152 ok; 153check_node_set("blipp[@id and @test]",[E]) -> 154 #xmlElement{name=blipp, 155 attributes=Atts} = E, 156 true = lists:keymember(id,#xmlAttribute.name,Atts), 157 true = lists:keymember(test,#xmlAttribute.name,Atts), 158 ok; 159check_node_set(Pattern,NodeSet) -> 160 io:format("Pattern: ~p~nNodeSet: ~p~n",[Pattern,NodeSet]), 161 error. 162 163xml_element_name(E,N) -> 164 #xmlElement{name=N} = E, 165 ok. 166 167ticket_6873() -> 168 [#xmlElement{}] = xmerl_xpath:string("//foo[contains(@bar, 'oe')]",element(1,xmerl_scan:string("<foo bar=\"Joe\" />"))), 169 ok. 170 171ticket_7496() -> 172 Test = fun(Doc, XPath, Exp) -> 173 Result = xmerl_xpath:string(XPath, Doc), 174 Exp = [Name || #xmlElement{name = Name} <- Result], 175 ok 176 end, 177 {Doc1,_} = xmerl_scan:string("<a><b/> <c/> <d/> <e/></a>"), 178 ok = Test(Doc1, "//b/following::*", [c, d, e]), 179 ok = Test(Doc1,"//b/following::*[1]", [c]), 180 ok = Test(Doc1,"//b/following::*[position()=1]", [c]), 181 ok = Test(Doc1,"//b/following::*[3]", [e]), 182 ok = Test(Doc1,"//b/following::*[position()=3]", [e]), 183 ok = Test(Doc1,"//e/preceding::*", [b, c, d]), 184 ok = Test(Doc1,"//e/preceding::*[1]", [d]), 185 ok = Test(Doc1,"//e/preceding::*[position()=1]", [d]), 186 ok = Test(Doc1,"//e/preceding::*[3]", [b]), 187 ok = Test(Doc1,"//e/preceding::*[position()=3]", [b]), 188 ok = Test(Doc1,"//b/following::*[position() mod 2=0]", [d]), 189 ok = Test(Doc1,"//b/self::*", [b]), 190 191 {Doc2,_} = xmerl_scan:string("<a><b/> <c><d/></c> <e/> <f><g/></f> <h/> <i><j/></i> <k/></a>"), 192 ok = Test(Doc2,"//g/preceding::*", [b, c, d, e]), 193 ok = Test(Doc2, "//g/following::*", [h, i, j, k]), 194 ok = Test(Doc2,"//g/ancestor::*", [a, f]), 195 ok = Test(Doc2,"//g/ancestor::*[1]", [f]), 196 ok = Test(Doc2,"//g/ancestor::*[2]", [a]), 197 ok = Test(Doc2,"//g/ancestor-or-self::*", [a, f, g]), 198 ok = Test(Doc2,"//g/ancestor-or-self::*[1]", [g]), 199 ok = Test(Doc2,"//g/ancestor-or-self::*[2]", [f]), 200 ok = Test(Doc2,"//g/ancestor-or-self::*[3]", [a]), 201 ok = Test(Doc2,"/descendant::*", [a, b, c, d, e, f, g, h, i, j, k]), 202 ok = Test(Doc2,"//f/preceding-sibling::*", [b, c, e]), 203 ok = Test(Doc2,"//f/following-sibling::*", [h, i, k]), 204 ok = Test(Doc2,"//f/self::*", [f]), 205 ok = Test(Doc2,"//f/ancestor::*", [a]), 206 ok = Test(Doc2,"//f/descendant::*", [g]), 207 ok = Test(Doc2,"//f/preceding::*", [b, c, d, e]), 208 ok = Test(Doc2,"//f/following::*", [h, i, j, k]), 209 ok = Test(Doc2,"//text()[1]/following-sibling::*", [c, e, f, h, i, k]), 210 211 {Doc3,_} = xmerl_scan:file("documentRoot.xml"), 212 ok = Test(Doc3,"//child",[child,child,child]), 213 ok = Test(Doc3,"//child[@name='beta']",[child]), 214 [{xmlAttribute,id,[],[],[],_,1,[],"2",false}] = 215 xmerl_xpath:string("/documentRoot/parent/child[@name='beta']/@id",Doc3), 216 ok = Test(Doc3,"/documentRoot/parent/child|/documentRoot/parent/pet", 217 [child,child,child,pet,pet]), 218 ok = Test(Doc3,"//*[starts-with(local-name(),'p')]", 219 [parent,pet,pet]). 220 221 222functions() -> 223 Test = fun(Doc, XPath, Exp) -> 224 Result = xmerl_xpath:string(XPath, Doc), 225 Exp = [begin 226 case Obj of 227 #xmlElement{name = EName} -> 228 EName; 229 #xmlAttribute{name = AName} -> 230 AName; 231 #xmlText{value=Text} -> 232 Text 233 end 234 end|| Obj <- Result], 235 ok 236 end, 237 Foo = 238 "<foo>" 239 " <bar>" 240 " <name>Xml</name>" 241 " <value>1</value>" 242 " </bar>" 243 " <bar>" 244 " <name>Xpath</name>" 245 " <value>2</value>" 246 " </bar>" 247 " <bar>" 248 " <name>Erlang</name>" 249 " <value>3</value>" 250 " </bar>" 251 "</foo>", 252 {Doc,_} = xmerl_scan:string(Foo), 253 ok = Test(Doc,"/foo/bar[name = 'Xml']/value/text()",["1"]), 254 ok = Test(Doc,"/foo/bar/node()/text()", 255 ["Xml","1","Xpath","2","Erlang","3"]), 256 ok = Test(Doc,"/foo/bar[contains(name, 'path')]",[bar]), 257 ok = Test(Doc,"/foo/bar[starts-with(name, 'X')]",[bar,bar]), 258 ok = Test(Doc,"/foo/bar[value = string(1)]/value/text()",["1"]), 259 260 261 {Doc2,_}= xmerl_scan:file("purchaseOrder.xml"), 262 ok = Test(Doc2,"//*[starts-with(local-name(),'c')]", 263 ['apo:comment',city,city,comment]), 264 ok = Test(Doc2,"//*[starts-with(name(),'c')]", 265 [city,city,comment]), 266 ok = Test(Doc2,"//*[starts-with(name(),'{http://www.example.com/PO1')]", 267 ['apo:purchaseOrder','apo:comment']). 268 269 270namespaces() -> 271 {Doc,_} = xmerl_scan:file("purchaseOrder.xml", [{namespace_conformant, true}]), 272 273 %% Element name using regular namespace and context namespace declaration. 274 [#xmlElement{nsinfo = {_, "purchaseOrder"}}] = 275 xmerl_xpath:string("/apo:purchaseOrder", Doc), 276 [#xmlElement{nsinfo = {_, "purchaseOrder"}}] = 277 xmerl_xpath:string("/t:purchaseOrder", Doc, [{namespace, [{"t", "http://www.example.com/PO1"}]}]), 278 279 %% Wildcard element name using regular namespace and context namespace declaration. 280 [#xmlElement{nsinfo = {_, "comment"}}] = 281 xmerl_xpath:string("./apo:*", Doc), 282 [#xmlElement{nsinfo = {_, "comment"}}] = 283 xmerl_xpath:string("./t:*", Doc, [{namespace, [{"t", "http://www.example.com/PO1"}]}]), 284 285 %% Attribute name using regular namespace and context namespace declaration. 286 [#xmlAttribute{nsinfo = {_, "type"}}, #xmlAttribute{nsinfo = {_, "type"}}] = 287 xmerl_xpath:string("//@xsi:type", Doc), 288 [#xmlAttribute{nsinfo = {_, "type"}}, #xmlAttribute{nsinfo = {_, "type"}}] = 289 xmerl_xpath:string("//@t:type", Doc, [{namespace, [{"t", "http://www.w3.org/2001/XMLSchema-instance"}]}]), 290 291 %% Wildcard attribute name using regular namespace and context namespace declaration. 292 [#xmlAttribute{nsinfo = {_, "type"}}, #xmlAttribute{nsinfo = {_, "type"}}] = 293 xmerl_xpath:string("//@xsi:*", Doc), 294 [#xmlAttribute{nsinfo = {_, "type"}}, #xmlAttribute{nsinfo = {_, "type"}}] = 295 xmerl_xpath:string("//@t:*", Doc, [{namespace, [{"t", "http://www.w3.org/2001/XMLSchema-instance"}]}]), 296 ok. 297