XSLT验证适用于第一个for-each然后失败

时间:2015-10-19 05:08:38

标签: xml xslt-1.0

我使用XSLT验证文档,但它没有按照我预期的方式工作。

我有一个XML文档,其中每个LodgementInstructionsLodgementDocument都有一对Counterparts,其中每个都有一组InvolvedParties。我想确保每个&#39;对应的&#39;我基于InvolvedParties拥有相同的PartyId,因此这是我的计划:对于每个LodgementDocumentLodgementInstructions,请获取所有InvolvedParties的一组Counterparts全部$setOfAllCounterpartPartyIdsCounterpart。然后,针对每个$setOfAllCounterpartPartyIds比较PartyId,将$partyIdsForThisCounterpart s用于该对应项,<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> ... 。如果它们是相同的,一切都很好;如果它们不同,那么我构建一条错误消息。

但是,我看到的行为是第一个对应方通过差异测试,但第二个失败,即使节点集看起来对我来说也是如此。这是我的调试输出:

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

我正在使用http://exslt.org/set/index.html中的设置差异功能,但我不认为问题出在这里,因为我已经将它换掉并使用了Sal Mangano的设定操作&#39 ; s XSLT Cookbook (第1章和第9章)并得到了相同的结果。

我假设我的函数式编程思维集是歪斜的。我无法理解为什么第二次迭代时集合差异失败。任何人都可以看到我可能做错了吗?

这是XML文档:

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

而且,我正在使用这个样式表:

xlsxwriter

1 个答案:

答案 0 :(得分:1)

我还没有彻底完成逻辑,但据我所知,您需要一组不同的PartyID ,而您的代码正在寻找不同的PartyID 节点< / em>的。两个不同的节点可能具有相同的值。

我担心XSLT 1.0中的这种问题非常棘手。我希望看到Muenchian分组的内容:为您的PartyID值定义一个键,当您遇到特定的PartyID时,将其替换为具有该特定值的第一个PartyID;一旦你完成了这个,不同的节点将代表不同的值。