XSLT - 使用第一个数据从类似名称的兄弟中获取数据

时间:2013-11-28 02:13:27

标签: xslt

我是一名正在学习的XSLT新手。我已经设法做了一些更简单的选择,对于每个循环,但不明白做我的下一个目标需要什么。 以下是输入xml的示例。

我要做的是在哪里是董事会,看看它的价值(在B的下面的例子中)。由于B表示底部,因此我想查看其中值为EdgeBottom的兄弟组件,并返回此兄弟组件的值。

请注意,这可能是TBLR或这些选项的任意组合,我想从每个相应的组件中提取材料详细信息。

我将输出到一张桌子中但是一旦我知道它是如何完成的,我就可以解决这个问题了。请原谅上面的任何术语错误,以及缺少任何非工作代码示例。非常感谢。

<Report schema="1.0">
    <Item id="74" name="cabinet">
        <VSection id="0" vsection="main">
            <HSection id="3">
                <Component id="2" idfull="07400302">
                    <DisplayName>EdgeBottom</DisplayName>
                    <Category>Edging</Category>
                    <Brand>Edging</Brand>
                    <Color>Edging</Color>
                    <Material>0.4mm Edging</Material>
                </Component>
                <Component id="1" idfull="07400301">
                    <DisplayName>Board</DisplayName>
                    <Category>Carcass</Category>
                    <Brand>Laminate</Brand>
                    <Color>White</Color>
                    <Material>16White</Material>
                    <Edging>B</Edging>
                    <IsEdgedOnTop>No</IsEdgedOnTop>
                    <IsEdgedOnRight>No</IsEdgedOnRight>
                    <IsEdgedOnBottom>Yes</IsEdgedOnBottom>
                    <IsEdgedOnLeft>No</IsEdgedOnLeft>
                    <EdgeMatTop>0.4mm</EdgeMatTop>
                    <EdgeMatRight>0.4mm</EdgeMatRight>
                    <EdgeMatBottom>0.4mm</EdgeMatBottom>
                    <EdgeMatLeft>0.4mm</EdgeMatLeft>
                </Component>
            </HSection>
        </VSection>
    </Item>
    <DocumentProperties>
    </DocumentProperties>
</Report>

1 个答案:

答案 0 :(得分:1)

假设您被定位在“董事会”组件上......

<xsl:template match="Component[DisplayName='Board']">

然后你可以使用前兄弟轴来使用一系列 xsl:if 条件获取 Component 元素,如下所示:

  <xsl:if test="contains(Edging,  'B')">
     <xsl:apply-templates select="preceding-sibling::Component[DisplayName='EdgeBottom']"/>
  </xsl:if>
  <xsl:if test="contains(Edging,  'T')">
     <xsl:apply-templates select="preceding-sibling::Component[DisplayName='EdgeTop']"/>
  </xsl:if>

然后您可以使用一个模板来输出'Edging'组件的值。例如

<xsl:template match="Component[Category='Edging']">
   <edging>
      <xsl:value-of select="Material" />
   </edging>
</xsl:template>

如果您想简化一些事情,可以将 xsl:if 条件合并为一个语句。如果边缘的可能值确实是“EdgeTop”,“EdgeBottom”,“EdgeLeft”和“EdgeRight”那么这些中的每一个的第五个字符显然是“T”,“B”,“L”和“R”并且所以可以直接针对当前组件进行检查,如此......

<xsl:apply-templates 
     select="preceding-sibling::Component
                [contains(current()/Edging, substring(DisplayName, 5, 1))]"/>

以下是一个示例XSLT,演示了这一点......

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/">
      <xsl:apply-templates select="//Component[DisplayName='Board']" />
   </xsl:template>

   <xsl:template match="Component[DisplayName='Board']">
      <xsl:apply-templates select="preceding-sibling::Component[contains(current()/Edging, substring(DisplayName, 5, 1))]"/>
   </xsl:template>

   <xsl:template match="Component[Category='Edging']">
      <edging>
         <xsl:value-of select="Material" />
      </edging>
   </xsl:template>
</xsl:stylesheet>

请注意,如果 Component 元素可能是以下兄弟,而不仅仅是前一个兄弟,请尝试使用此表达式:

<xsl:apply-templates 
     select="../Component
               [Category='Edging']
               [contains(current()/Edging, substring(DisplayName, 5, 1))]"/>