今天遇到一个问题,对于下面这样一个xml串
<opDetail> <recordInfo> <fieldInfo> <fieldChName>告警流水号</fieldChName> <fieldEnName>alarmId</fieldEnName> <fieldContent>GJ_2816071613_352385154_2970760107_588354443</fieldContent> </fieldInfo> <fieldInfo> <fieldChName>告警ID</fieldChName> <fieldEnName>alarmStaId</fieldEnName> <fieldContent>2014070200101</fieldContent> </fieldInfo> </recordInfo> </opDetail>
如何转换成下面这种形式:
<opDetail> <recordInfo> <alarmId>GJ_2816071613_352385154_2970760107_588354443</alarmId> <alarmStaId>2014070200101</alarmStaId> </recordInfo> </opDetail>
根据之前在项目中配置各种解析脚本的经验,我的直觉告诉我通过xquery脚本,是可以实现这么一个转换过程,而且,之前在看《Xquery权威指南》一书时,曾看到类似的例子,于是我翻开《xquery权威指南》,根据目录提示,很快我就找到了解决办法,很简单,就是使用xquery构造元素。
使用xquery构造元素,有两种方式:直接元素构造(Direct element Construction)和计算构造(Computed Construction),下面来分别介绍:
- 直接元素构造
这种构造方式比较简单,比较容易理解。根据书中的描述“直接构造器,使用类似XML语法,用于创建名称固定的元素和属性。”当初看这句话,并没有给予太多关注,“使用类似XML语法”我感觉这是废话,而后面“
用于创建名称固定的元素和属性
”这句话则直接被我忽视了。而在解决上面的问题时,我才意识到这句话的重要性。作者的意思是,直接元素构造,适合使用与节点名称和属性名称已知的元素构造,而在我们遇到的问题中,节点的名称是未知的,因此不能使用直接元素构造的方式进行。说到现在,可能大家还不知道直接元素构造是怎么一回事,举两个栗子吧。
<opDetail> <recordInfo> { for $a in //fieldInfo return <name>{$a/fieldEnName/text()}</name> } </recordInfo> </opDetail>
在stylus-studio中针对问题中的xml串运行上面的脚本,得到如下结果:
<opDetail><recordInfo><name>alarmId</name><name>alarmStaId</name></recordInfo></opDetail>
可以看到在这里,节点opDetail,recordInfo以及name的名称都是固定的。
再比如
<opDetail> <recordInfo> { for $a in //fieldInfo return <name fieldChName="{$a/fieldChName/text()}">{$a/fieldEnName/text()}</name> } </recordInfo> </opDetail>
在stylus-studio中针对问题中的xml串运行上面的脚本,得到如下结果:
<opDetail><recordInfo><name fieldChName="告警流水号">alarmId</name><name fieldChName="告警ID">alarmStaId</name></recordInfo></opDetail>
- 计算构造
element html { element h1 { "This is a Test"} }
运行之后,返回的结果是
<html><h1>This is a Test</h1></html>
如果针对问题中的xml串,执行下面的语句
element opDetail { for $a in //fieldInfo return element {$a/fieldEnName/text()} {$a/fieldContent/text()} }
返回的结果是
<opDetail><alarmId>GJ_2816071613_352385154_2970760107_588354443</alarmId><alarmStaId>2014070200101</alarmStaId></opDetail>
此外,还可以这样,节点名称使用固定字符串+运算结果的方式进行,同样对问题中的xml文,执行下面的语句:
element opDetail { for $a in //fieldInfo return element {concat("ele",$a/fieldEnName/text())} {$a/fieldContent/text()} }
返回的结果是
<opDetail><elealarmId>GJ_2816071613_352385154_2970760107_588354443</elealarmId><elealarmStaId>2014070200101</elealarmStaId></opDetail>
更多的栗子就不多介绍了,翻开《xquery权威指南》第五章,你可以找到很多栗子。