2011-08-10 4 views
0

문제점이 있습니다. 과거의 방식으로 작동하지 못하고 지식이 풍부한 일부 전문가가 솔루션을 제공 할 수 있기를 기대합니다.Groovy XMLSlurper가 스키마와 일치하도록 문서를 업데이트합니다.

시퀀스가 ​​포함 된 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. 요소가 있으면 해당 값을 업데이트하십시오. 예 : resultCode "005009"에 대해 entriesEmployeeId 값을 "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 출력을 찾고 있어요 (첫 번째 결과의 값이 업데이트되어 있습니다, 두 번째는 삽입 -하지만 바로 이곳에서 ... 다른 요소가있을 수 거기도!) :

<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

를, 내가 좋아하는 코드를 보았다.add (2, aNode),하지만 입력하려고 할 때이 시그니처가있는 "add"메서드를 찾지 못합니다. 내가 사용해야하는 다른 jar 파일이 있습니까? – Mark

답변

0

확인, 진행. 다행스럽게도 스키마를 제어 할 수 있으므로 "시퀀스"를 "모두"로 변경했습니다. "all"은 0 또는 1의 "minOccurs"를 허용하므로 선택적으로 처리 할 수 ​​있습니다. 필자는 여러 번 발생할 수있는 하나의 요소를 반복 할 수있는 요소가 포함 된 하나의 선택적 요소로 리팩터링했습니다.

"all"은 모든 주문 (선택 사항)을 허용하므로 끝에 추가하는 것과 같이 아무 곳이나 추가 할 수 있습니다.

는 기존의 것을 찾기위한,이 작품 :

codeNode.children().find { it.name() == "resultReporter" } 

나는 그것이 정말 존재하는지이 코드의 결과에 "() IsEmpty 함수"를 테스트합니다.

So : 일반적인 솔루션 (예 : 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()) 
     } 
    } 
}