If you produce this XML and it is for configuration purposes, then making it more readable has its purpose. I use XML for configuration a lot and I only use attributes when really applicable.
I would write it like this:
<Configuration>
<Ftp>
<Host>LOCALHOST</Host>
<Port>25</Port>
</Ftp>
<Pop3>
<Host>LOCALHOST/<Host>
<Port>110</Port>
<Interval>30000</Interval>
</Pop>
<Smtp>
<Host>LOCALHOST</Host>
<Port>25</Port>
</Smtp>
</Configuration>
Using some other format, then XML, is also a solution. But if you stick to XML then my answer is one way to organize XML in a human readable fasion. Also if you avoid attributes then conversion to JSON for instance is very simple.
Even if XML is bloated with markup I find it readable if structured well. And although it was meant for computer data exchange I find it very good for configuration files. YAML looks fine, but for me it lacks that explicit structure :)
Update:
Due to the request for the code I updated the answer with additional info. To get XML like mine bellow, all you have to do is change one procedure. On the other hand this is basic XML handling so I advise you to learn it.
function TConnXml.ReadString(const Section, Key, Default: string): string;
var
Node: IXMLNode;
Child: IXMLNode;
begin
Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(Section);
if not Assigned(Node) then
begin
Result := Default;
Exit;
end;
Child:= Node.FindNode(Key);
if not Assigned(Child) then
begin
Result := Default;
Exit;
end;
Result := Child.Text;
end;
procedure TConnXml.WriteString(const Section, Key, Value: string);
var
Node: IXMLNode;
Child: IXMLNode;
begin
if ReadString(Section, Key, '') = Value then
Exit;
Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(Section);
if not Assigned(Node) then
Node := fXMLDoc.DocumentElement.AddChild(Section);
Child:= Node.ChildNodes.FindNode(Key);
if not Assigned(Child) then
Child:= Node.AddChild(Key);
Child.Text := Value;
fModified := True;
Save;
end;
I wrote it without testing so there may be some mistakes in it, but that is the code you should use.