2015-10-19 53 views
0

我使用XSLT驗證文檔,它不按我預期的方式工作。XSLT驗證工作的第一個爲每個然後失敗

我有一個XML文檔,其中每個LodgementInstructionsLodgementDocument有一對Counterparts,並且其中每個都有一組InvolvedParties。我想確保每個'對口'具有基於PartyId的相同組InvolvedParties,所以這是我的計劃:對於每個LodgementDocumentLodgementInstructions,獲得跨所有Counterparts,$setOfAllCounterpartPartyIds的所有InvolvedParties的集合。然後,對於每個Counterpart,將$setOfAllCounterpartPartyIdsPartyId的集合相比較,$partyIdsForThisCounterpart。如果他們一樣,一切都很好;如果它們不同,我會生成一條錯誤消息。

但是,我看到的行爲是第一個對手通過差異測試,但第二個失敗,即使節點集看起來對我來說也是一樣。這是我的調試輸出:

<SemanticErrors xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

    document IDs 
    LI1402992691249 

     Counterpart ID [CP1402992691548] 
     setOfAllCounterpartPartyIds = [<PartyId>1</PartyId><PartyId>2</PartyId>]    
     partyIdsForThisCounterpart = [<PartyId>1</PartyId><PartyId>2</PartyId>]       
     Are [<PartyId>1</PartyId><PartyId>2</PartyId>] and [<PartyId>1</PartyId><PartyId>2</PartyId>] the same? [true] 

     Counterpart ID [CP1402992694237] 
     setOfAllCounterpartPartyIds = [<PartyId>1</PartyId><PartyId>2</PartyId>]    
     partyIdsForThisCounterpart = [<PartyId>1</PartyId><PartyId>2</PartyId>]       
     Are [<PartyId>1</PartyId><PartyId>2</PartyId>] and [<PartyId>1</PartyId><PartyId>2</PartyId>] the same? [false] 

      Validation error: 
      Those elements that are in the first set but not the second: 
      <PartyId>1</PartyId><PartyId>2</PartyId> 

      ... 

我使用的是從http://exslt.org/set/index.html差集功能,但我不認爲這個問題是在這裏,因爲我已經換出來,並用於從薩爾曼加諾的XSLT設置操作食譜(第1章和第9章)並得到了相同的結果。

我假設我的函數式編程思維集是歪斜的。我不明白爲什麼在第二次迭代中設置差異失敗。任何人都可以看到我可能做錯了什麼?

這是XML文檔:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<LodgementVerification> 
    <LodgementCase>   
     <ElnLodgementCaseId>12345</ElnLodgementCaseId> 
     <LodgementInstructions> 
      <ElnDocumentId>LI1402992691249</ElnDocumentId> 
      <Counterpart> 
       <Counterpart> 
        <CounterpartData> 
         <ElnCounterpartId>CP1402992691548</ElnCounterpartId> 
         <ElnLodgementCaseId>1402986735664</ElnLodgementCaseId> 
         <ElnDocumentId>LI1402992691249</ElnDocumentId> 
         <CounterpartContent> 
          <LodgementInstructions> 
           <LodgementCaseDetail> 
            <DocumentCount>1</DocumentCount> 
           </LodgementCaseDetail> 
          </LodgementInstructions> 
         </CounterpartContent> 
         <InvolvedParty> 
          <PartyId>1</PartyId> 
          <PartyType>Organisation</PartyType> 
         </InvolvedParty> 
         <InvolvedParty> 
          <PartyId>2</PartyId> 
          <PartyType>Organisation</PartyType> 
         </InvolvedParty> 
        </CounterpartData> 
       </Counterpart> 
      </Counterpart> 
      <Counterpart> 
       <Counterpart> 
        <CounterpartData> 
         <ElnCounterpartId>CP1402992694237</ElnCounterpartId> 
         <ElnLodgementCaseId>1402986735664</ElnLodgementCaseId> 
         <ElnDocumentId>LI1402992691249</ElnDocumentId> 
         <InvolvedParty> 
          <PartyId>1</PartyId> 
          <PartyType>Organisation</PartyType> 
         </InvolvedParty> 
         <InvolvedParty> 
          <PartyId>2</PartyId> 
          <PartyType>Organisation</PartyType> 
         </InvolvedParty> 
        </CounterpartData> 
       </Counterpart> 
      </Counterpart> 
     </LodgementInstructions> 
     <DocumentCount>1</DocumentCount> 
     <LodgementDocument> 
      <ElnDocumentId>M1402987029798</ElnDocumentId> 
      <Counterpart> 
       <Counterpart> 
        <CounterpartData> 
         <ElnCounterpartId>CP1402992691501</ElnCounterpartId> 
         <ElnDocumentId>M1402987029798</ElnDocumentId> 
         <InvolvedParty> 
          <PartyId>1</PartyId> 
          <PartyType>Organisation</PartyType> 
         </InvolvedParty> 
         <InvolvedParty> 
          <PartyId>2</PartyId> 
          <PartyType>Organisation</PartyType> 
         </InvolvedParty> 
        </CounterpartData> 
       </Counterpart> 
      </Counterpart> 
      <Counterpart> 
       <Counterpart> 
        <CounterpartData> 
         <ElnCounterpartId>CP1402992691500</ElnCounterpartId> 
         <ElnDocumentId>M1402987029798</ElnDocumentId> 
         <InvolvedParty> 
          <PartyId>1</PartyId> 
          <PartyType>Organisation</PartyType> 
         </InvolvedParty> 
         <InvolvedParty> 
          <PartyId>2</PartyId> 
          <PartyType>Organisation</PartyType> 
         </InvolvedParty> 
        </CounterpartData> 
       </Counterpart> 
      </Counterpart> 
     </LodgementDocument> 
    </LodgementCase> 
</LodgementVerification> 

而且,我使用這個樣式表:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

    <xsl:template match="/"> 
     <SemanticErrors> 

      <xsl:for-each select="//LodgementInstructions | //LodgementDocument"> 
       <xsl:variable name="elnDocumentId" select="ElnDocumentId"/> 
       <xsl:variable name="elnDocumentIDs" select="./Counterpart/Counterpart/CounterpartData/ElnDocumentId"/> 
       <xsl:call-template name="CheckInvolvedParties"> 
        <xsl:with-param name="elnDocumentIDs" select="$elnDocumentIDs"/> 
       </xsl:call-template>     
      </xsl:for-each> 

     </SemanticErrors> 
    </xsl:template> 


    <!-- Check if each counterpart for a document ID contains the same set of involved-party reference IDs --> 
    <xsl:template name="CheckInvolvedParties">  
     <xsl:param name="elnDocumentIDs"/> 

     document IDs 
     <xsl:value-of select="$elnDocumentIDs"/> 

     <!-- For each document ID... --> 
     <xsl:for-each select="current()[ElnDocumentId=$elnDocumentIDs]"> 

      <xsl:variable name="setOfAllCounterpartPartyIds" select="set:distinct(//InvolvedParty/PartyId)" xmlns:set="http://exslt.org/sets"/>    

      <xsl:for-each select="Counterpart"> 
       <!-- For each document counterpart, make sure it contains just $setOfAllCounterpartPartyIds... -->       
       <xsl:call-template name="ValidateCounterpartsPartyIds"> 
        <xsl:with-param name="setOfAllCounterpartPartyIds" select="$setOfAllCounterpartPartyIds"/>     
       </xsl:call-template> 
      </xsl:for-each>   
     </xsl:for-each> 
    </xsl:template> 


    <!-- --> 
    <xsl:template name="ValidateCounterpartsPartyIds">   
     <xsl:param name="setOfAllCounterpartPartyIds"/> 

     <!-- Check if there are any counterparts to check. --> 
     <xsl:if test="./*[text()]">      
      Counterpart ID [<xsl:value-of select="Counterpart/CounterpartData/ElnCounterpartId"/>] 
      setOfAllCounterpartPartyIds = [<xsl:copy-of select="$setOfAllCounterpartPartyIds"/>] 
      <xsl:variable name="partyIdsForThisCounterpart" select="Counterpart/CounterpartData/InvolvedParty/PartyId"/> 
      partyIdsForThisCounterpart = [<xsl:copy-of select="Counterpart/CounterpartData/InvolvedParty/PartyId"/>] 
      <xsl:variable name="setDifference" select="set:difference($setOfAllCounterpartPartyIds, $partyIdsForThisCounterpart)" xmlns:set="http://exslt.org/sets"/>    
      Are [<xsl:copy-of select="$setOfAllCounterpartPartyIds"/>] and [<xsl:copy-of select="$partyIdsForThisCounterpart"/>] the same? [<xsl:value-of select="count($setDifference) = 0"/>] 

      <xsl:if test="count($setDifference) > 0" xmlns:set="http://exslt.org/sets">     
       Validation error: 
       Those elements that are in the first set but not the second: 
       <xsl:copy-of select="$setOfAllCounterpartPartyIds[count(. | $partyIdsForThisCounterpart) != count($partyIdsForThisCounterpart)]"/>       
      </xsl:if>      
     </xsl:if>   
    </xsl:template>  

</xsl:stylesheet> 
+0

爲什麼要用XSLT驗證文檔?這是語法的工作,如XML Schema,Relax NG或Schematron ... – potame

+0

@potame:我非常希望我可以使用XSLT以外的任務來完成此任務,但我維護一個遺留系統,並且我有一些固定限制。 – craigcaulfield

回答

0

我沒有通過邏輯的工作充分,但據我所看到的您需要一組不同的PartyID ,而您的代碼正在尋找不同的PartyID 節點。兩個不同的節點可能具有相同的值。

恐怕XSLT 1.0中的這種問題非常嚴重。我期望看到一些沿着Muenchian分組的線條:爲PartyID值定義一個鍵,並且當你遇到一個特定的PartyID時,用具有該特定值的第一個PartyID替換它;一旦你完成了這些,不同的節點將代表不同的值。

相關問題