XSL父选择器

时间:2012-07-15 13:58:20

标签: xslt

XML

<dsInventory>
  <Room>
    <RoomName>kantoor 1</RoomName>
    <RoomId>1376257</RoomId>
  </Room>
  <Room>
    <RoomName>Hal</RoomName>
    <RoomId>1376258</RoomId>
  </Room>
<Method>
    <RoomId>1376257</RoomId>
    <Name>test</Name>
  </Method>
<Method>
    <RoomId>1376258</RoomId>
    <Name>test</Name>
  </Method>
</dsInventory>

XSL

 <xsl:for-each select="/dsInventory/Room">
        <xsl:for-each select="/dsInventory/Method">
             <xsl:if test="RoomId=../RoomId">
             </xsl:if>
         </xsl:for-each>
    </xsl:for-each>

问题

我正在尝试根据宽限期选择相应房间的方法。但是选择器../RoomId不起作用。如何从第一个获得RoomId的价值?或者选择房间方法的正确方法是什么?

3 个答案:

答案 0 :(得分:0)

这里的问题是背景。 if条件失败,因为它从Method个节点的上下文运行,因此XPath表达式../RoomID正在RoomID上查找dsInventory节点。没有这样的节点。

你没有说出你想要的输出,但是基于你只想迭代房间并找到每个方法的假设,试试这个:(注意我也使用模板而不是每个循环,在XSL中最好避免使用。

您可以运行它并在 this XML Playground 处查看输出。

<!-- kick things off from the point of dsInventory -->
<xsl:template match="dsInventory">
    <ul><xsl:apply-templates select='Room' /></ul>
</xsl:template>

<!-- room nodes -->
<xsl:template match='Room'>
    <xsl:variable name='method' select='../Method[RoomId = current()/RoomId]' />
    <li>
        <xsl:value-of select='concat(RoomName," (",RoomId,")")' />:
        method = <xsl:value-of select='concat($method/Name," (",$method/RoomId,")")' />
    </li>
</xsl:template>

答案 1 :(得分:0)

您没有指定正在使用的XSLT版本或您预期的输出。我假设您想要XSLT 1.0,想要复制文档,但在Room下添加链接的方法名称并删除方法。

此XSLT 1.0样式表......

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />

<xsl:template match="@*|node()">
 <xsl:copy>
  <xsl:apply-templates select="@*|node()"/>
 </xsl:copy>
</xsl:template>

<xsl:template match="Method"/>

<xsl:template match="Room">
 <xsl:copy>
  <xsl:apply-templates select="@*|node()"/>
  <xsl:apply-templates select="../Method[RoomId=current()/RoomId]/Name"/>
 </xsl:copy>
</xsl:template>

</xsl:stylesheet>

...当应用于您的样本输入文档时,将生成...

<dsInventory>
  <Room>
    <RoomName>kantoor 1</RoomName>
    <RoomId>1376257</RoomId>
    <Name>test</Name>
  </Room>
  <Room>
    <RoomName>Hal</RoomName>
    <RoomId>1376258</RoomId>
    <Name>test</Name>
  </Room>
</dsInventory>

说明

使用current()函数指定相对于Room模板的序列构造函数的当前项,在本例中是Room元素。在谓词中,我们将current()/ RoomId与select表达式的Method步骤的RoomId进行比较。因此,链接的名称将复制到Room下。没有xsl:if,没有xsl:for-each,没有变量。所有这些都可以使用current()函数在select表达式中实现。

答案 2 :(得分:0)

<xsl:for-each select="/dsInventory/Room">
    <xsl:for-each select="/dsInventory/Method">
        <xsl:if test="RoomId=../RoomId"></xsl:if>
    </xsl:for-each>
</xsl:for-each>

正如回答此问题的人所指出的那样,您正在尝试将/dsInventory/Method/RoomId/dsInventory/RoomId进行比较,后者在提供的XML文档中不存在。

  

我试图根据相应房间选择方法   房间。

以下是一个完整的转换,展示了如何执行此操作:

<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="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="Room">
  <xsl:copy>
    <xsl:apply-templates/>
    <xsl:apply-templates mode="grab" 
         select="/*/Method[RoomId = current()/RoomId]"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Method" mode="grab">
  <xsl:copy>
   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="Method | Method/RoomId"/>
</xsl:stylesheet>

将此转换应用于以下XML文档(提供的更改方法名称 - 彼此不同):

<dsInventory>
    <Room>
        <RoomName>kantoor 1</RoomName>
        <RoomId>1376257</RoomId>
    </Room>
    <Room>
        <RoomName>Hal</RoomName>
        <RoomId>1376258</RoomId>
    </Room>
    <Method>
        <RoomId>1376257</RoomId>
        <Name>test1</Name>
    </Method>
    <Method>
        <RoomId>1376258</RoomId>
        <Name>test2</Name>
    </Method>
</dsInventory>

生成了想要的,正确的结果(添加到房间的方法和删除了顶部元素的Method子项):

<dsInventory>
   <Room>
      <RoomName>kantoor 1</RoomName>
      <RoomId>1376257</RoomId>
      <Method>
         <Name>test1</Name>
      </Method>
   </Room>
   <Room>
      <RoomName>Hal</RoomName>
      <RoomId>1376258</RoomId>
      <Method>
         <Name>test2</Name>
      </Method>
   </Room>
</dsInventory>

<强>解释

  1. identity rule 副本&#34; as-is&#34;选择执行它的每个节点。

  2. 覆盖身份模板的模板与Room匹配。这里Room元素是&#34;浅层复制,模板应用于它的子节点(为它们选择身份模板,并将它们复制到#34;原样&#34;到输出)和然后模板应用于任何Method,其RoomId子项与当前匹配的RoomId子项具有相同的值( current() ){ {1}}元素。因为我们以后想要删除任何Room元素,所以我们在此指定所需处理(与删除不同)将在Method模式下完成。

  3. 覆盖身份模板的第二个模板会删除所有"grab"个元素,只需简单匹配它们并拥有一个空体。

  4. 与模式Method中的Method匹配的模板只是浅层复制并将模板应用于其子项。在其子级中,"grab"仅与身份模板匹配,并按原样复制&#34;&#34;。 Name子项由比标识模板更具体的模板匹配,并且选择前者用于执行。所选择的模板没有正文,有效地删除&#34;删除&#34;输出中匹配的RoomId