Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ MUSHclient ➜ Development ➜ XML schema for MCL/XML files (worlds, plugins)?

XML schema for MCL/XML files (worlds, plugins)?

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Draeand   (5 posts)  Bio
Date Mon 22 Jul 2024 02:45 AM (UTC)
Message
Is there an (already existing) up to date XSD for MUSHclient MCL files/plugin files? I'd be happy to make one if people are interested, I just am uncertain how to verify that it's correct other than perhaps submitting it here as well as testing it against existing MCL/XML files. This might be a pretty niche use-case so for all I know one doesn't exist. Thought I would ask though!
Top

Posted by Nick Gammon   Australia  (23,070 posts)  Bio   Forum Administrator
Date Reply #1 on Mon 22 Jul 2024 08:24 AM (UTC)
Message
No, there isn't. I must admit that writing XML schemas is not one of my strengths.

I'm not totally sure what a schema is, except to guess that you validate the XML against a schema in order to determine whether it conforms to specifications (eg. a field which should contain a number actually contains a number).

What would the use of it be? Perhaps, if you are hand-writing a plugin you might want to make sure that the fields in the XML will be correctly processed?

You can probably get a good idea of the element names from: https://github.com/nickgammon/mushclient/blob/master/xml/xml_load_world.cpp

The options in the world file are validated against a table here: https://github.com/nickgammon/mushclient/blob/master/scriptingoptions.cpp

That would be a good place to see the allowable ranges for various elements.

For example:


{"spam_line_count",                     20,    O(m_iSpamLineCount), 5, 500 },                    
{"speed_walk_delay",                    0,     O(m_iSpeedWalkDelay), 0, 30000, OPT_FIX_SPEEDWALK_DELAY},                  


So the element spam_line_count is a number, and its allowable range is 5 to 500.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Draeand   (5 posts)  Bio
Date Reply #2 on Mon 22 Jul 2024 03:01 PM (UTC)
Message
Nick Gammon said:

No, there isn't. I must admit that writing XML schemas is not one of my strengths.

I'm not totally sure what a schema is, except to guess that you validate the XML against a schema in order to determine whether it conforms to specifications (eg. a field which should contain a number actually contains a number).

What would the use of it be? Perhaps, if you are hand-writing a plugin you might want to make sure that the fields in the XML will be correctly processed?

You can probably get a good idea of the element names from: https://github.com/nickgammon/mushclient/blob/master/xml/xml_load_world.cpp

The options in the world file are validated against a table here: https://github.com/nickgammon/mushclient/blob/master/scriptingoptions.cpp

That would be a good place to see the allowable ranges for various elements.

For example:


{"spam_line_count",                     20,    O(m_iSpamLineCount), 5, 500 },                    
{"speed_walk_delay",                    0,     O(m_iSpeedWalkDelay), 0, 30000, OPT_FIX_SPEEDWALK_DELAY},                  


So the element spam_line_count is a number, and its allowable range is 5 to 500.


Basically, a schema describes the structure of a document. It not only specifies the elements and attributes of the document but can also specify things like the number of occurrences of an attribute or element, the minimum and maximum of the element, a pattern to verify/validate that element, etc. And though they can be used for validation, you can also pass them to something like CodeSynthesis XSD to generate serialization/deserialization code from them.
There are two ways I know of to write schemas. One way is to use XML itself, although this is annoying and cumbersome, or you can use something like RelaxNG. As an example, I've tried to whip up a basic schema of all the possible elements/attributes, so using RelaxNG's compact representation, I can do something like:

muclient = element muclient {
    plugin?,
    include_*,
    world?,
    triggers?,
    aliases?,
    timers?,
    macros?,
    variables?,
    colours?,
    keypad?,
    printing?
}

world = element world {
    attribute world_file_version { xsd:long }?,
    attribute muclient_version { xsd:token }?,
    attribute date_saved { xsd:date }?,
    attribute accept_chat_connections { xsd:boolean }?,
    attribute alternative_inverse { xsd:boolean }?,
    attribute alt_arrow_recalls_partial { xsd:boolean }?,
# ...

The '?' in the above means optional (zero or one), the '*' means zero or more. If I had wanted to make one of these required, I would omit either a '*' or '?'. ("include" is a keyword in RelaxNG's compact form, hence the _ after it.) The "attribute" part is split into two parts: the name and the type. So
attribute world_file_version { xsd:long }?,
means that there is an attribute named "world_file_version" of type "xsd:long", where "xsd:long" is the type "long" within the XML schema definition language specification. I'm still learning this myself; I've never written a schema before, so I'm still learning how to, e.g., place constraints on elements and such in RNC. But it's really neat, and XML isn't the only language that's schematized.
I've already drafted a basic schema for the format, both because I'm working on a project of my own but in case someone else wants it. I'm just uncertain if I've made elements required that shouldn't be required, or optional where they should be required, little things like that; looking through the code makes it difficult to tell what's required and what isn't, so I've just opted for the safest rout (assume that pretty much everything can be optional, worry about that not being the case later). It makes the code a bit annoying to use, but the generate code lets me do something like:

#include "mushclient.h" // mushclient.h is the schema file, can obviously rename it
#include <format>
#include <iostream>

// Assume we've already read the file into an istream called input_stream
// Parse it
const auto doc = muclient_(input_stream);
if (!doc) {
    // Parse failed
}
// Now, we can access the world:
const auto world = doc->world();
if (!world) { // world isn't present
    // Do something
}
const auto name = world->name(); // This is probably required, so I should make it so
std::cout << std::format("World name is {}\n", name);

For each attribute in the schema, the code generator generates a few methods: two for retrieving the attribute (one read-only, one read-write), and up to three setters (two make copies, one doesn't, and for optional attributes, one of those setters takes an std::optional<T> as a parameter, and only sets it if the optional isn't std::nullopt). So not only can you parse your documents but you can also build them from the ground up and serialize them.
Top

Posted by Nick Gammon   Australia  (23,070 posts)  Bio   Forum Administrator
Date Reply #3 on Mon 22 Jul 2024 08:27 PM (UTC)
Message
That looks nice. Well if you want to put a Github link to your schema we could play with it.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Draeand   (5 posts)  Bio
Date Reply #4 on Wed 24 Jul 2024 12:50 AM (UTC)
Message
My schema is here, both in RelaxNG's compact format (RNC) and as an XML schema definition: https://github.com/ethindp/mushclient-schemas

I have managed to get it successfully validating with world files with Jing, but I'm still trying to get plugins to validate. Jing is being overly strict with whitespace, so I'm trying to resolve that problem, as well as a couple other issues with things like the `date-written` attribute, which looks like it'd fit `xsd:dateTime` but it isn't validating. I feel like an (excellent) test-suite for this in the future could probably be running a validator over the entire plugins directory of a MUSHclient install as well as some test worlds from simple to very complex worlds as a starting point, but that's for later.
Top

Posted by Nick Gammon   Australia  (23,070 posts)  Bio   Forum Administrator
Date Reply #5 on Wed 24 Jul 2024 02:09 AM (UTC)
Message
You should probably make the world name, IP address (site) and port number required fields, as the client won't let you view other configuration tabs until they are filled in.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Draeand   (5 posts)  Bio
Date Reply #6 on Wed 24 Jul 2024 04:04 AM (UTC)
Message
Done! :) I also made id required since I assume the client will auto-generate that, so it being empty would be really odd.
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


1,463 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.