我遇到了一个问题,我似乎无法继续前进,并希望你们中的一些知识渊博的专家可以提供解决方案。
我有一个包含序列的XSD文档。如您所知,这意味着所有元素必须以指定的顺序出现。我需要使用它,因为它们中的一些也是可选的(minOccurs =“0”)。
以下是架构的简化部分:
<xs:element name="result">
<xs:complexType>
<xs:sequence>
<xs:element ref="tns:resultCode"/>
<xs:element ref="tns:resultAbbreviations" minOccurs="0"/>
<xs:element ref="tns:resultReporter" minOccurs="0"/>
<xs:element ref="tns:vendorData" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
XML文档的相关部分:
<lab:order>
<lab:results>
<lab:result>
<lab:resultCode>005009</lab:resultCode>
<lab:resultAbbreviations>
<lab:resultAbbreviation>FOO</lab:resultAbbreviation>
</lab:resultAbbreviations>
<lab:resultReporter>
<lab:enteredEmployeeId>86118</lab:enteredEmployeeId>
</lab:resultReporter>
<lab:vendorData value="123" key="ABC"/>
<lab:vendorData value="ABC" key="123"/>
</lab:result>
<lab:result>
<lab:resultCode>005025</lab:resultCode>
</lab:result>
...
我需要做两件事:
我已经能够在“结果”节点的末尾添加一个节点,但无法使查找工作更新,也无法将节点插入适当的位置以满足XSD。这是代码:
...
//-- ResultReporter: enteredEmployeeId, verifiedEmployeeId
// Must add to proper result, based on code
ResultReporter reporter = nextResult.getReporter();
NodeChild codeNode = getResultNodeFor( nextResult.getCode() );
if( codeNode != null ) { //found proper result - does reporter exist already?
def reporterNode = codeNode.find { it.name() == 'resultReporter' }
if( !reporterNode.isEmpty() ) { //reporter node exists - update it
reporterNode.'lab:enteredEmployeeId'( nextResult.getReporter().getEnteredEmployeeId() )
} else { //element does not exist - add new one
codeNode.appendNode {
'lab:resultReporter' {
'lab:enteredEmployeeId'(nextResult.getReporter().getEnteredEmployeeId())
}
}
}
} else { //not found
throw new IllegalArgumentException("Cannot add reporter for nonexistent result code: " + nextResult.getCode() );
}
...
/**
* @param aCode
* @return the Node with resultCode = aCode, else null
*/
private NodeChild getResultNodeFor( String aCode ) {
for( def nextResult : labDoc.order.results.children() ) {
if( nextResult.resultCode.text().equals(aCode) ) { //found
return nextResult;
}
}
return null; //not found
}
我正在寻找这样的XML输出(注意第一个结果的值被更新,第二个被插入 - 但是在正确的位置......那里也可能有其他元素!):
<lab:order>
<lab:results>
<lab:result>
<lab:resultCode>005009</lab:resultCode>
<lab:resultAbbreviations>
<lab:resultAbbreviation>FOO</lab:resultAbbreviation>
</lab:resultAbbreviations>
<lab:resultReporter>
<lab:enteredEmployeeId>EntVal</lab:enteredEmployeeId>
</lab:resultReporter>
<lab:vendorData value="123" key="ABC"/>
<lab:vendorData value="ABC" key="123"/>
</lab:result>
<lab:result>
<lab:resultCode>005025</lab:resultCode>
<lab:resultReporter>
<lab:enteredEmployeeId>EntVal</lab:enteredEmployeeId>
</lab:resultReporter>
</lab:result>
...
所以:谁能告诉我如何使这项工作?谢谢!标记
答案 0 :(得分:0)
好的,进步。幸运的是,我可以控制模式,所以我将“序列”更改为“全部”。 “all”允许“minOccurs”为0或1,所以我可以用这种方式处理。我重构了一个可能多次出现的元素,它是一个包含可重复元素的可选元素。
由于“all”允许任何订单(和可选),我可以在任何地方添加,例如追加到最后。
至于寻找现有的,这是有效的:
codeNode.children().find { it.name() == "resultReporter" }
我在这段代码的结果上测试“isEmpty()”,看它是否真的存在。
所以:不是一般解决方案(例如,如果我无法更改XSD),但适用于我需要的东西。希望这有助于其他人。
如果有人知道如何解决这个问题,请说出来!
只是提供完整的解决方案,以下是用于更改XML的代码:
def reporterNode = codeNode.children().find { it.name() == "resultReporter" }
if( !reporterNode.isEmpty() ) { //reporter node exists - update it
reporterNode.replaceNode { node ->
'lab:resultReporter'() {
'lab:enteredEmployeeId'(nextResult.getReporter().getEnteredEmployeeId())
}
}
} else { //element does not exist - add new one
codeNode.appendNode {
'lab:resultReporter' {
'lab:enteredEmployeeId'(nextResult.getReporter().getEnteredEmployeeId())
}
}
}