我有一个XML文档,如下所示:
<Root>
<Cover>
<Cover_Ref Val="1"/>
<Cover_Code Val="Food in transit"/>
<AdditionalCover>
<AdditionalCover_Area Val="Sussex"/>
</AdditionalCover>
</Cover>
<Cover>
<Cover_Ref Val="2"/>
<Cover_Code Val="Frozen goods"/>
</Cover>
<Cover>
<Cover_Ref Val="3"/>
<Cover_Code Val="Business equipment"/>
<AdditionalCover>
<AdditionalCover_Area Val="Sussex"/>
</AdditionalCover>
</Cover>
<AdditionalCoverResult>
<CoverArea Val="Sussex"/>
<CoverExcluded Val="N"/>
</AdditionalCoverResult>
<AdditionalCoverResult>
<CoverArea Val="Sussex"/>
<CoverExcluded Val="Y"/>
</AdditionalCoverResult>
</Root>
我需要把它变成这样的东西:
<Insurances>
<Insurance>
<reference>1</reference>
<CoverType>Food in transit</CoverType>
<Region>Sussex</Region>
<Excluded>N</Excluded>
</Insurance>
<Insurance>
<reference>2</reference>
<CoverType>Frozen goods</CoverType>
</Insurance>
<Insurance>
<reference>3</reference>
<CoverType>Business equipment</CoverType>
<Region>Sussex</Region>
<Excluded>Y</Excluded>
</Insurance>
</Insurances>
AdditionalCoverResult元素引用包含AdditionalCover元素的Cover元素 - 因此第一个Cover元素的封面不排除,而第三个Cover元素的封面不包括在内。第二个封面元素没有AdditionalCover,因此没有引用它的AdditionalCoverResult元素。
我的问题是在<xsl:for-each select="//Cover">
循环内我无法想出一种识别我应该寻找哪个AdditionalCoverResult元素的方法。在for-each中使用position()
最终导致我错误地输出了没有AdditionalCover的Cover元素的AdditionalCoverResult信息。
我必须保留Cover的原始顺序,所以我不能做两个单独的循环,一个用于Cover with AdditionalCover,一个用于Cover而不用AdditionalCover。
在//Cover
返回的节点集中,有一种方法可以识别上下文节点在//Cover[AdditionalCover]
返回的节点集中的位置吗?
我有点猜测,对于Cover元素,我需要思考“我在//Cover[AdditionalCover]
内的索引是什么,以便我可以使用该索引来识别我对应的AdditionalCoverResult元素?”
答案 0 :(得分:1)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<Insurances>
<xsl:apply-templates select="Cover"/>
</Insurances>
</xsl:template>
<xsl:template match="Cover">
<Insurance>
<xsl:apply-templates/>
</Insurance>
</xsl:template>
<xsl:template match="Cover_Ref">
<reference><xsl:value-of select="@Val"/></reference>
</xsl:template>
<xsl:template match="Cover_Code">
<CoverType><xsl:value-of select="@Val"/></CoverType>
</xsl:template>
<xsl:template match="AdditionalCover_Area">
<Region><xsl:value-of select="@Val"/></Region>
<Excluded>
<xsl:value-of select=
"/*/AdditionalCoverResult[CoverArea/@Val=current()/@Val]
[position()
=
1 +count(current()
/ancestor::Cover[1]
/preceding-sibling::Cover
[AdditionalCover
/AdditionalCover_Area/@Val
=
current()/@Val
]
)
]
/CoverExcluded/@Val
"/>
</Excluded>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档时:
<Root>
<Cover>
<Cover_Ref Val="1"/>
<Cover_Code Val="Food in transit"/>
<AdditionalCover>
<AdditionalCover_Area Val="Sussex"/>
</AdditionalCover>
</Cover>
<Cover>
<Cover_Ref Val="2"/>
<Cover_Code Val="Frozen goods"/>
</Cover>
<Cover>
<Cover_Ref Val="3"/>
<Cover_Code Val="Business equipment"/>
<AdditionalCover>
<AdditionalCover_Area Val="Sussex"/>
</AdditionalCover>
</Cover>
<AdditionalCoverResult>
<CoverArea Val="Sussex"/>
<CoverExcluded Val="N"/>
</AdditionalCoverResult>
<AdditionalCoverResult>
<CoverArea Val="Sussex"/>
<CoverExcluded Val="Y"/>
</AdditionalCoverResult>
</Root>
生成想要的正确结果:
<Insurances>
<Insurance>
<reference>1</reference>
<CoverType>Food in transit</CoverType>
<Region>Sussex</Region>
<Excluded>N</Excluded>
</Insurance>
<Insurance>
<reference>2</reference>
<CoverType>Frozen goods</CoverType>
</Insurance>
<Insurance>
<reference>3</reference>
<CoverType>Business equipment</CoverType>
<Region>Sussex</Region>
<Excluded>Y</Excluded>
</Insurance>
</Insurances>
答案 1 :(得分:0)
您可以将您感兴趣的当前上下文的一部分存储在变量中 - 例如:
<xsl:for-each select="//Cover">
...
<xsl:variable name="additional" select="AdditionalCover/AdditionalCover_Area/@Val"/>
<xsl:if select="$additional">
<Excluded>
<xsl:value-of select="AdditionalCoverResult[CoverArea/@Val = $additional]/CoverExcluded/@Val"/>
</Excluded>
</xsl:if>
</xs:for-each>
答案 2 :(得分:0)
发布问题后,我在相关部分看到了一个链接 - xpath/xslt to determine index of context node relative to all nodes of same name?
Dimitre Novatchev的回答表明,使用
count(preceding::question)+1
您可以找到当前上下文节点相对于文档中所有question
元素的索引。
对于我的问题,我使用了count(preceding::Cover[AdditionalCover])+1
并且它有效 - 我希望我能正确理解它,但它确实可以解决这个问题。
我不会立即选择这个作为正确的答案,因为如果有人有任何其他方法可以做到这一点我会非常感兴趣 - 我可能是XSLT的中级水平,这是一个学习更多关于它!