How can you tell if you are over-engineering your code?

In what circumstances should you decide to design your code like the example below?

In this example, they made it clear that formats other than XML are possible. They also mentioned about the structure of the chat messages being defined by a standard called XMPP.

But how can you make these decisions, for example, if you do not know XML or XMPP? If you do not know what other possibilities can cause future tech requirement changes? If you do not have the right knowledge, how can you make the right decisions and therefore avoid over-engineering (or improperly engineering) your code?

Also, what factors can tell if code is over-engineered?

For instance, the chat app from one of my previous projects needed to relay chat messages from chat servers to the app’s UI. Chat messages were encoded using XML. We knew not to pass XML straight to the view controllers. That wasn’t enough. The structure of the chat messages were defined by yet another standard called XMPP. We could have easily modeled the struct that carries chat messages in a way that mirrors the XMPP spec. We decided to model the struct based on the appearance properties of chat messages so that our view controllers would not be tightly coupled to the chat server technology. We didn’t want to be locked into XMPP.

Additional Questions
Do you design your code this way in the beginning of feature development without knowing what future feature changes will be? What if this feature gets removed someday?

@jab2109 please see above