0

This is and example of the XML for Pioneer Rekordbox DJ Software.

  • Using Python, I am trying to re-sort the XML child tags by the START attribute for each POSITION_MARK tag. The POSITION MARK tag basically represent cue points for the DJ software.

I looked at this Stackoverflow question, but they only sort by whole numbers, not floats:

Python sort XML elements by and tag and attributes recursively

But I need to sort by the float value in each attribute.

  • Each TRACK tag has POSITION_MARK child tags with a Start attribute float value.
  • How do you re-sort the POSITION_MARK child tags by there float number in the Start attribute.
  • This way when it rewrites the XML, each TRACK tags POSITION_MARK children are sorted in ascending order (smallest to largest) by their Start attribute value which is a float value.

How do you sort in Python using xmltree sorted to re-sort the POSITION_MARK children by their START attribute that contain float values?

<?xml version="1.0" ?>
<DJ_PLAYLISTS>
    <COLLECTION>

       <TRACK>        
          <POSITION_MARK Start="22.093" />
          <POSITION_MARK Start="44.162" />
          <POSITION_MARK Start="88.300" />
          <POSITION_MARK Start="110.369" />
          <POSITION_MARK Start="132.438" />
          <POSITION_MARK Start="11.059" />
          <POSITION_MARK Start="220.714" />
          <POSITION_MARK Start="242.783" />
       </TRACK>
    
       <TRACK>        
          <POSITION_MARM Start="0.024" />
          <POSITION_MARK Start="30.024" />
          <POSITION_MARK Start="60.024" />
          <POSITION_MARK Start="90.024" />
          <POSITION_MARK Start="120.024" />
          <POSITION_MARK Start="150.024" />
          <POSITION_MARK Start="180.024" />
       </TRACK>

    </COLLECTION>
 </DJ_PLAYLISTS>
1
  • Two things: 1) Show the code of your attempt. Include a minimal, reproducible example. 2) XML attribute values are treated as strings by default and so sort as strings by default. You'll need to take this into account in your sorting algorithm. Commented Sep 12, 2023 at 15:42

1 Answer 1

1

xml.etree.ElementTree.Element objets are designed to look / feel like lists. Sadly they are not actually lists, and don't support list.sort, however if you slice them you do get a list of sub-elements in the range. So given an element e, e[:] will return a list of all its children elements.

You can then sort that in-place, then use slice-setting (e[:] = ...) to replace the existing sequence of children by the now-sorted list.

doc = ET.fromstring(doc)
# iterate all the TRACK elements
for track in doc.iterfind(".//TRACK"):
    # get a list of the track's children (POSITION_MARK)
    children = track[:]
    # sort in place, using the `Start` attribute interpreted as a float (by actually parsing it to a float)
    children.sort(key=lambda e: float(e.get('Start')))
    # set the now-sorted children back on
    track[:] = children
print(ET.tostring(doc, encoding='unicode'))

However, sorted takes an iterable, which an Element is, so you can use that to get-and-sort the sub-elements in a single operation. And since it also returns a list, you can then directly set the result back as above:

doc = ET.fromstring(doc)
for track in doc.iterfind(".//TRACK"):
    track[:] = sorted(track, key=lambda e: float(e.get('Start')))
print(ET.tostring(doc, encoding='unicode'))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.