3
$\begingroup$

I am having trouble to transform XML data into a Mathematica Dataset of Associations. I want a dataset that follows the structure of the XML file with all its sublevels. Here is the example xml:

<?xml version="1.0" encoding="utf-8"?>
<Readconfig version="1.0">
  <LVL1>
  
    <LVL2 attribute="1">
        <LVL3>
            <LVL4 attribute="11">
                <LVL5 attribute="111"/>
                <LVL5 attribute="112"/>
                <LVL5 attribute="113"/>
                <LVL5 attribute="114"/>
            </LVL4>
        </LVL3>
    </LVL2>
    
    <LVL2 attribute="2">
        <LVL3>
            <LVL4 attribute="21">
              <LVL5 attribute="211"/>
              <LVL5 attribute="212"/>
              <LVL5 attribute="213"/>
              <LVL5 attribute="214"/>
              <LVL5 attribute="215"/>
              <LVL5 attribute="216"/>
            </LVL4>
            
            <LVL4 attribute="22">
              <LVL5 attribute="221"/>
              <LVL5 attribute="223"/>
              <LVL5 attribute="224"/> 
              <LVL5 attribute="225"/>
              <LVL5 attribute="226"/>
              <LVL5 attribute="227"/>
              <LVL5 attribute="228"/>
            </LVL4>
        </LVL3>
    </LVL2>
    
    <LVL2 attribute="3">
        <LVL3>
            <LVL4 attribute="31">
              <LVL5 attribute="311"/>     
            </LVL4>
        </LVL3>
    </LVL2>
    
  </LVL1>
 
</Readconfig>

I tried:

Dataset@Cases[myXMLdata, 
  XMLElement[_, attrs_, _] :> Association[attrs], Infinity]

but it only shows the Dataset of the lowest levels. Also note that the XML file might change structure and i dont want to hardcode any levels of the XML file. Does anyone have a simple solution?

$\endgroup$
1
  • 3
    $\begingroup$ Some elements have attributes AND sub elements e.g.: "{XMLElement["LVL2", {"attribute" -> "1"}, {XMLElement["LVL3",...." How do you want this represent in an association? $\endgroup$ Commented Jan 12, 2022 at 15:35

1 Answer 1

4
$\begingroup$

This is one way:

xml = ImportString["the provided complete xml", "XML"];

Part 2 of the imported xml the actual data skipping the xml version and encoding. Then repeatedly apply a rule and convert to a dataset:

ds = xml[[2]] //
     ReplaceRepeated[XMLElement[tag : _String, attrs : _List, value : _List] :> 
       <|"tag" -> tag, "attributes" -> <|attrs|>, "value" -> value|>] //
     Dataset

this is the resulting dataset:

enter image description here

drill down to the value of the Readconfig tag:

enter image description here

drill down to the deepest level:

enter image description here

$\endgroup$
1
  • $\begingroup$ Great answer. Works very well! $\endgroup$
    – heartbeatz
    Commented Jan 18, 2022 at 13:37

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.