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>
     ...

次の 2 つのことを実行できる必要があります。

  1. 要素が存在する場合は、その値を更新します。たとえば、resultCode「005009」のenteredEmployeeId値を「EntVal」に変更します。これには、その要素が存在するかどうかを調べる必要があります。
  2. 要素が存在しない場合は、スキーマに従って検証に合格する場所に追加します。たとえば、resultCode "005025" に resultReporter とenteredEmployeeId を追加します。上記の 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 出力を探しています (最初の結果の値が更新され、2 番目の結果の値が挿入されることに注意してください。ただし、適切な場所に... 他の要素も存在する可能性があります!):

   <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 であるため、オプションをそのように処理できます。複数回発生する可能性のある 1 つの要素を、繰り返し可能な要素を含む 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 に答える