我使用XSLT驗證文檔,它不按我預期的方式工作。XSLT驗證工作的第一個爲每個然後失敗
我有一個XML文檔,其中每個LodgementInstructions
或LodgementDocument
有一對Counterparts
,並且其中每個都有一組InvolvedParties
。我想確保每個'對口'具有基於PartyId
的相同組InvolvedParties
,所以這是我的計劃:對於每個LodgementDocument
或LodgementInstructions
,獲得跨所有Counterparts
,$setOfAllCounterpartPartyIds
的所有InvolvedParties
的集合。然後,對於每個Counterpart
,將$setOfAllCounterpartPartyIds
與PartyId
的集合相比較,$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>
爲什麼要用XSLT驗證文檔?這是語法的工作,如XML Schema,Relax NG或Schematron ... – potame
@potame:我非常希望我可以使用XSLT以外的任務來完成此任務,但我維護一個遺留系統,並且我有一些固定限制。 – craigcaulfield