Here we have an XMLObject["Document"]:

(* gives an XMLObject["Document"] *)
myXML = ImportString["<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"HTMLFiles/xhtml-math11-f.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head><title>Feeling like Job today :(</title></head>
<body><p>Oh. Dear!</p></body></html>", {"XHTML", "XMLObject"}];

This just confirms that x is indeed an XMLObject["Document"]:

f1[x_] := (Echo[Head@x, "Head of arg:"]; Echo[FullForm@x, "FullForm of arg:"];)

(* Output:
Head of arg:  XMLObject[Document]

FullForm of arg:  XMLObject["Document"][List[XMLObject["Declaration"][Rule["Version","1.0"],Rule["Standalone","yes"]]],XMLElement["html",List[Rule[List["http://www.w3.org/2000/xmlns/","xmlns"],"http://www.w3.org/1999/xhtml"]],List[XMLElement["head",List[],List[XMLElement["title",List[],List["Feeling like Job today :("]]]],XMLElement["body",List[],List[XMLElement["p",List[],List["Oh. Dear!"]]]]]],List[]]

And now we try to match this as the arg type for a function:

f2[x_XMLObject]:=Echo["Yay, we got called!","f2:"];
f3[x_XMLObject["Document"]]:=Echo["Yay, we got called!","f3:"];
f4[x_XMLObject[type_String]]:=Echo["Yay, we got called!","f4:"];
f5[x_XMLObject[type_]]:=Echo["Yay, we got called!","f5:"];
f6[x_XMLObject[___]]:=Echo["Yay, we got called!","f6:"];


(*Expected: f2 might remain unevaluated, but f2, f3, f4, f5, f6 report getting called*)
(*Actual: f2, f3, f4, f5 remain unevaluated; f6 is invoked:
f6:  Yay, we got called!

Regrettably, in the case of f6, only the head of the argument is available in the function, making f1 with its completely untyped, unpatterned argument the only one of my attempts that worked.

Surely it is possible to write a clean, fully specified argument pattern for XMLObject["Document"], and clearly I am missing something fundamental about how patterns are matched. But what?

Thank you for your help!


2 Answers 2


You may use a pattern with a condition, like:

MatchQ[myXML, x_ /; Head[x] == XMLObject["Document"]]


With this you may then define e.g.:

f1[x_ /; Head[x] == XMLObject["Document"]]:= "Yes, this is an XMLObject."


"Yes, his is an XMLObject."
  • $\begingroup$ That worked a treat, thank you very much! And while your suggestion has fixed my immediate problem, it raises another question: Shouldn’t the x_somehead syntax do precisely what your restriction is doing? $\endgroup$ Sep 22, 2023 at 19:58
  • 2
    $\begingroup$ @FelixKasza - the issue is the precedence between the _ and [...] operators. You would think that x_XMLObject["Document"] is the same as x_(XMLObject["Document"]) but really it's equivalent to (x_XMLObject)["Document"]. $\endgroup$
    – Jason B.
    Sep 22, 2023 at 20:50
  • $\begingroup$ @JasonB. -- I feel a little stupid, but very much enlightened now. Thank you! I am off to try this! $\endgroup$ Sep 23, 2023 at 21:17

This is a syntax issue with the pattern notation. Consider this from your f3:

(* Pattern[x,Blank[XMLObject]]["Document"] *)

So, your "pattern" isn't actually a well-formed pattern, it's an expression with a pattern as its head. I'm not even sure what that would match. Instead, try something like this:

f3[x : XMLObject["Document"][___]] := ...

Or something like this:

f3[x_?(EqualTo[XMLObject["Document"]]@*Head)] := ...
  • $\begingroup$ Thank you! I'll certainly remember to look at the FullForm of patterns I have problems with! The ":" notation by itself does not cure my badly-constructed pattern (I had tried those variations before posting), but I think with this together with Jason B.'s comment above, I may better understand my error. $\endgroup$ Sep 23, 2023 at 21:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.