将节点的值与以下兄弟节点匹配

时间:2013-12-03 11:21:10

标签: xslt

以下是我正在尝试的代码xml代码段:

<Shipment>
<Operation>Insert</Operation>
<Creation_Date>2013-12-02</Creation_Date>
<Line_Id>10023<Line_Id>
<Country_of_origin>US</Country_of_origin>
</Shipment>
<Shipment>
<Operation>Insert</Operation>
<Creation_Date>2013-12-3</Creation_Date>
<Line_Id>10023<Line_Id>
<Country_of_origin>US</Country_of_origin>
</Shipment>
<Shipment>
<Operation>Update</Operation>
<Creation_Date>2013-12-3</Creation_Date>
<Line_Id>10023<Line_Id>
<Country_of_origin>US</Country_of_origin>
</Shipment>

在这种情况下,所有Shipement标签中字段的值相同,我们需要传递该值,即Country_of_origin应该作为US传递。

但是如果在任何Shipement节点中,该字段的值不是first的值,则应该将其作为null传递。

例如:

<Shipment>
<Operation>Insert</Operation>
<Creation_Date>2013-12-02</Creation_Date>
<Line_Id>10023<Line_Id>
<Country_of_origin>US</Country_of_origin>
</Shipment>
<Shipment>
<Operation>Insert</Operation>
<Creation_Date>2013-12-3</Creation_Date>
<Line_Id>10023<Line_Id>
<Country_of_origin>US</Country_of_origin>
</Shipment>
<Shipment>
<Operation>Update</Operation>
<Creation_Date>2013-12-3</Creation_Date>
<Line_Id>10023<Line_Id>
<Country_of_origin>FR</Country_of_origin>
</Shipment>

在这种情况下,字段Country_of_origin的值应作为NULL传递,因为第三个货件标记中的Country_of_origin字段值携带的值(FR)不同于第一个(US)。

有人可以帮忙吗?这里的货件标签可以多次出现。

1 个答案:

答案 0 :(得分:2)

我定义了一个变量

<xsl:variable name="country"
    select="(Shipment/Country_of_origin)[1]
             [not(. != ../../Shipment/Country_of_origin)]" />

如果所有货物都有相同的原产国,则该变量将设置为该值,如果不是,则将其设置为空字符串(从技术上讲,它将设置为{{ 1}}元素从第一次发货,或到一个空节点集/序列,但转换为字符串时,您将获得所需的值)。这里有第一个Country_of_origin针对自身的冗余检查,但由于这永远不会Shipment,因此不会影响结果。

现在,您只需将此变量值用作所有货件的!=内容。

您在评论中说明您的真实XML有几个这些发货部分:

Country_of_origin

并且您需要单独为每个<Header> <Line> <Shipment>...</Shipment> <Shipment>...</Shipment> ... </Line> <Line>...</Line> </Header> 执行此过程。在这种情况下,您不能使用全局变量,而是需要在正确的位置计算适当的值,然后在模板参数中将其传递给链。在XSLT 2.0中,使用隧道参数很容易:

Line

在1.0中你没有隧道参数,所以你必须在每个级别明确地传递参数,而你没有<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:template match="@*|node()"> <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy> </xsl:template> <xsl:template match="Line"> <xsl:next-match> <xsl:with-param name="country" tunnel="yes" select="(Shipment/Country_of_origin)[1] [not(. != ../../Shipment/Country_of_origin)]" /> </xsl:next-match> </xsl:template> <xsl:template match="Country_of_origin"> <xsl:param name="country" tunnel="yes" /> <xsl:copy> <xsl:value-of select="$country" /> </xsl:copy> </xsl:template> </xsl:stylesheet> 所以你必须使用next-match

call-template