0

我遇到了一个问题,我似乎无法解决问题,希望你们中的一些知识渊博的专家可以提供解决方案。

我有一个包含序列的 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>
     ...

我需要能够做两件事:

  1. 如果元素存在,则更新其值。例如,将结果代码“005009”的enteredEmployeeId 值更改为“EntVal”。这需要确定该元素是否存在。
  2. 如果元素不存在,请将其添加到将根据架构通过验证的位置。例如,为 resultCode“005025”添加 resultReporter 和输入的EmployeeId。请注意,如上面的 XML 片段中所示,可能存在也可能不存在可选元素。

我已经能够在“结果”节点的末尾添加一个节点,但无法让查找工作更新,也无法将节点插入到正确的位置以满足 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>
     ...

所以:谁能告诉我如何使这项工作?谢谢!标记

4

1 回答 1

0

好,进步。幸运的是,我可以控制架构,因此我将“序列”更改为“全部”。“all”允许“minOccurs”为 0 或 1,所以我可以通过这种方式处理可选的。我将可能多次出现的一个元素重构为一个包含可以重复的元素的可选元素。

由于“全部”允许任何顺序(和可选),我可以在任何地方添加,例如附加到末尾。

至于找到现有的,这是有效的:

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())
        }
    }
}
于 2011-08-11T14:20:03.710 回答