I would like to extract from an XMLObject only the XMLElements with a specific tag.

Inspired from the Mathematica help (section transforming XML, introduction, the example with the colours), I have tried this code :

Definition of the XMLObject:

XMLtest = 
    XMLElement["YO", {}, 
      {XMLElement["YO", {}, 2], 
         XMLElement["BA", {}, 
           {XMLElement["YO", {}, 
             {XMLElement["BA", {}, 2]}], XMLElement["BA", {}, 2]}]}]]

enter image description here

Code so as to suppress all the elements different from "YO" in order to keep only the elements with the tag "YO":

XMLtest2 = XMLtest /. XMLElement[Except["YO"], _, _] -> Sequence[]

enter image description here

The above code works well.

Code so as to suppress the XMLElements without the tag "BA":

XMLtest2 = XMLtest /. XMLElement[Except"BA", _, _] -> Sequence[]

enter image description here

For this latter code, I have a problem with the answer because I obtain only the XMLObject. However, I would like to obtain a tree of XMLElements under the XMLObject.

Please help me to correct my code in this lastRoutine clean-up case?

  • $\begingroup$ Somehow you ended up with the \[RightArrow] character when instead you need either plain text -> or \[Rule]. Correct this and your replacement will work. I am closing this question as a "simple syntax error" now. If you find that I am mistaken or have other problem please comment here, starting your comment with @Mr.Wizard so that I will be notified. $\endgroup$ – Mr.Wizard May 17 '15 at 13:35
  • $\begingroup$ Sometimes I like this way of defining a behavior for an XML element: xmltest2 = Block[{XMLElement}, XMLElement["BA", __] := Sequence[]; XMLtest] and xmltest3 = Block[{XMLElement}, XMLElement[Except["YO"], __] := Sequence[]; XMLtest]. $\endgroup$ – Michael E2 May 17 '15 at 13:44
  • $\begingroup$ @MichaelE2 That seems harder than using DeleteCases; do you find otherwise? $\endgroup$ – Mr.Wizard May 17 '15 at 14:37
  • 2
    $\begingroup$ @Mr.Wizard For any given narrow task, there is probably a simpler solution than the one I proposed. But when I use XML data, which is not often so take this with a grain of salt, I often want to do several things that are functions of the tag, attributes, and data. I find it easier to think about such a problem in terms of XMLElement as a function. OTOH, there is a difference I overlooked at first. The OP's code would do one replacement, mine three, due to ReplaceAll vs. evaluation. So maybe my comment isn't so helpful here. $\endgroup$ – Michael E2 May 17 '15 at 14:55
  • $\begingroup$ @MichaelE2 I made some corrections. Thanks a lot for your very constructive help. $\endgroup$ – Bendesarts May 17 '15 at 21:47

I'm still not sure what you want. I think it is this, but it does not reproduce the tree you have in the question for the Except["YO"] case.

contractElement[xml_, tagpat_] := Block[{XMLElement},
   XMLElement[tagpat, _, data_] /; FreeQ[data, XMLElement] := Sequence[];
   XMLElement[tagpat, _, data_] := Sequence @@ data;

contractElement[XMLtest, Except["YO"]] // TreeForm
contractElement[XMLtest, Except["BA"]] // TreeForm

Mathematica graphics Mathematica graphics

Side note: I thought the syntax for XMLObject is XMLObject[type][data], which does not quite conform with you example. For instance, this might produce an error, if a root is required:

XMLtest2 = 
   XMLElement["YO", {},
    {XMLElement["BA", {}, 2], 
     XMLElement["BA", {},
      {XMLElement["YO", {}, 2],
       XMLElement["BA", {}, 2]}]}]];
XMLtest2 // TreeForm
contractElement[XMLtest2, Except["BA"]] // TreeForm

Mathematica graphics Mathematica graphics

  • $\begingroup$ Thank a lot for your help. Your code perfectly answers to my need. However, I would prefer a code with an approach as in this post : mathematica.stackexchange.com/questions/83622/… That is to say a way which easily permit to add more conditions on the attributes of an XMLElements. Thank you for your help. $\endgroup$ – Bendesarts May 18 '15 at 21:05
  • $\begingroup$ You can define XMLElement[tag_, attr_, data_] := ... however you want. Such as XMLElement[tag_, attr_, data_] := XMLElement[tag, Join[attr, myattributes], data], if you wish to add a list myattributes` to the list of attribute attr. $\endgroup$ – Michael E2 May 18 '15 at 21:49
  • $\begingroup$ @Bendesarts please, take a tour. $\endgroup$ – Kuba May 19 '15 at 5:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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