Well, I m trying to create a RELAX NG schema for PRTG advanced sensor output. Unfortunately the XML specification is a terrible mess IMHO, but I tried anyway.
Basically there are two possible results:
- Success: There can be a
Text
element and there will be at least oneResult
element. - Error: There will be an
Error
element and (an optional?)Text
element, too.
So my schema starts like this:
<?xml version="1.0" encoding="utf-8"?>
<!-- RELAX NG specification for PRTG Advanced Sensors -->
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:a="http://relaxng.org/ns/annotation/1.0">
<start>
<element name="Prtg">
<choice>
<interleave><!-- error -->
<element name="Error"><ref name="C.Boolean" /></element>
<element name="Text"><ref name="DT.Message" /></element>
</interleave>
<interleave><!-- success -->
<optional>
<element name="Text"><ref name="DT.Message" /></element>
</optional>
<oneOrMore>
<element name="Result">
<interleave>
<element name="Channel"><text /></element>
<element name="Value"><text /></element>
<ref name="PRTG-TagSoup" />
</interleave>
</element>
</oneOrMore>
</interleave>
</choice>
</element>
</start>
<!-- ... -->
</grammar>
C.Boolean
is basically 0
or 1
, and DT.Message
is basically <text />
.
PRTG-TagSoup
is a set of all-optional elements that excludes Text
, Error
, and Result
.
I would say it s clear what is an error, and what is success, but xmllint
seems to have trouble with that:
I get error messages like this:
element Prtg: Relax-NG validity error : Expecting an element Error, got nothing
element Result: Relax-NG validity error : Invalid sequence in interleave
Relax-NG validity error : Extra element Text in interleave
element Prtg: Relax-NG validity error : Element Prtg failed to validate content
A sample input that triggers those messages is:
<?xml version="1.0" encoding="UTF-8"?>
<!--MonitoringOutput v0.2 id=id-16371 (PRTG.xsl v0.0.3)-->
<Prtg>
<!--status_string=OK-->
<!--Exit Code: 0-->
<Text>OK</Text>
<Result>
<Channel>wr_wait</Channel>
<Value>0.938023</Value>
<!--range: min="0"-->
</Result>
<!-- ... -->
<Result>
<Channel>rd_wait</Channel>
<Value>0</Value>
<!--range: min="0"-->
</Result>
</Prtg>
Somehow my guess is that xmllint
seeing the Text
element does not know which branch to take.
Even if I move the Text
element after the last Result
element, it does not parse.
Missing Parts
这里是失踪的那部分人,留待强调核心问题(正如我看到的那样):
<define name="C.Boolean">
<choice datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<value type="integer">0</value>
<value type="integer">1</value>
</choice>
</define>
<define name="DT.Message">
<data datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
type="string">
<param name="pattern">".{0,2000}"</param>
</data>
</define>
<define name="PRTG-TagSoup">
<a:documentation>
Unordered set of optional elements.
The actual logic is hard to get from the specification.
</a:documentation>
<zeroOrMore>
<choice>
<!--- many more... -->
<element name="CustomUnit"><text /></element>
<element name="Float"><ref name="C.Boolean" /></element>
<element name="Warning"><ref name="C.Boolean" /></element>
<element name="ShowChart"><ref name="C.Boolean" /></element>
<element name="ShowTable"><ref name="C.Boolean" /></element>
<element name="LimitErrorMsg"><text /></element>
<element name="LimitWarningMsg"><text /></element>
<element name="LimitMode"><ref name="C.Boolean" /></element>
<element name="ValueLookup"><text /></element>
<element name="NotifyChanged"><empty /></element>
</choice>
</zeroOrMore>
</define>