2

我有一个如下所示的 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 的原始顺序,所以我不能做两个单独的循环,一个用于带有 AdditionalCover 的 Cover,一个用于不带 AdditionalCover 的 Cover。

在返回的节点集中,//Cover有没有一种方法可以识别上下文节点在返回的节点集中的位置//Cover[AdditionalCover]

我有点猜测,对于 Cover 元素,我需要考虑“我在什么索引中,//Cover[AdditionalCover]以便我可以使用该索引来识别我相应的 AdditionalCoverResult 元素?”

4

3 回答 3

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>
于 2012-05-26T04:39:57.260 回答
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>
于 2012-05-25T10:11:28.693 回答
0

发布问题后,我在相关部分看到了一个链接 - xpath/xslt 以确定上下文节点相对于所有同名节点的索引?

Dimitre Novatchev 的回答指出,通过使用

count(preceding::question)+1

您可以找到当前上下文节点相对于question文档中所有元素的索引。

对于我使用的问题count(preceding::Cover[AdditionalCover])+1并且它有效 - 我希望我已经正确理解它,但它似乎确实可以解决问题。

我不会立即选择此作为正确答案,因为如果有人有任何其他方法,我会非常感兴趣 - 我可能是 XSLT 的中级水平,这是了解更多信息的好机会!

于 2012-05-25T10:11:54.750 回答