【发布时间】:2018-07-25 16:20:28
【问题描述】:
我正在尝试创建一种强定义的 xml 语言,但在元素标记之间的元素值方面遇到了麻烦。我希望它们被视为一个字符串,除非它们没有用引号括起来。这是我为演示这个想法而创建的基本语法:
grammar org.xtext.example.myxml.MyXml hidden(WS)
generate myXml "http://www.xtext.org/example/myxml/MyXml"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
Element:
{Element}
'<Element' attributes+=ElementAttribute* ('/>' | '>'
subElement+=SubElement*
'</Element' '>')
;
SubElement:
{SubElement}
'<SubElement' attributes+=SubElementAttribute* ('/>' | '>'
value=ElementValue
'</SubElement' '>')
;
ElementAttribute:
NameAttribute | TypeAttribute
;
SubElementAttribute:
NameAttribute
;
TypeAttribute:
'type' '=' type=STRING
;
NameAttribute:
'name' '=' name=STRING
;
ElementValue hidden():
value=ID
;
terminal STRING:
'"' ( '\\' . /* 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' */ | !('\\'|'"') )* '"' |
"'" ( '\\' . /* 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' */ | !('\\'|"'") )* "'"
;
terminal WS: (' '|'\t'|'\r'|'\n')+;
terminal ID: '^'?('a'..'z'|'A'..'Z'|'_'|'0'..'9'|':'|'-'|'('|')')*;
这是一个演示其用法的测试:
@Test
def void parseXML() {
val result = parseHelper.parse('''
<Element type="myType" name="myName">
<SubElement>some string:like-stuff here </SubElement>
</Element>
''')
Assert.assertNotNull(result)
val errors = result.eResource.errors
for (error : errors) {
println(error.message)
}
}
我从这个确切的代码得到的错误是mismatched input 'string:like-stuff' expecting '</SubElement'
显然这是行不通的,因为ID 不允许空格,在ID 中添加空格可以修复上述错误,但会导致其他解析问题。所以我的问题是如何将元素值解析为类似字符串的表示形式,而不会导致解析器在其他领域产生歧义。我能够让它以我的完整语言以任何形式工作的唯一方法是将ElementValue 转换为ID's 的列表,以空格分隔。 (我无法让它在这个最小的例子上工作,但不确定有什么不同)
【问题讨论】:
-
是否有理由使用 Xtext 而不是使用 ecore xml 模式支持?
-
@ChristianDietrich 我对此不是很熟悉。我的最终需要是我需要能够解析和序列化这个 xml 文件。然后从我拥有的另一个语法(不是基于 xml 的)中,我想交叉引用这个模型中的某些元素。这是我可以用你提到的东西实现的吗?如果是这样,您介意为我指明正确的方向吗?
-
如果您安装了 emf sdk,您将能够将 xml 模式转换为 ecore,并为 help.eclipse.org/kepler/… 获取序列化和反序列化。通过实现 iresourceserviceprovider,您将能够从基于 xtext 的文件引用到基于 ecore 的文件
-
@ChristianDietrich 好的,我来看看。那么我原来的问题没有解决方案吗?除了那一个问题,我已经完成了语法,所以如果能解决它就很容易完成
标签: parsing xml-parsing xtext xtend