1

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 不起作用。如何从第一个 for-each 中获取 RoomId 的值?或者选择房间方法的正确方法是什么?

4

3 回答 3

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>

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

我正在尝试根据 roomid 选择相应房间的方法。

这是一个完整的转换,展示了如何做到这一点:

<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. 身份规则“按原样”复制选择执行它的每个节点。

  2. 覆盖身份模板的模板匹配Room. 这里Room元素是“浅拷贝,模板应用于其子元素(为它们选择标识模板,并将它们“按原样”复制到输出),然后将模板应用于 any Method,其RoomId子元素具有相同的值作为RoomId当前匹配current()Room_ Method_"grab"

  3. 覆盖标识模板的第二个模板Method通过简单地匹配它们并具有空主体来删除所有元素。

  4. 匹配Methodin 模式的模板"grab"只是简单地对其进行浅拷贝并将模板应用于其子项。在其子项中,Name仅由标识模板匹配并“按原样”复制。RoomId子项由比身份模板更具体的模板匹配,并选择前者执行。所选模板没有正文,这有效地Method/RoomId从输出中“删除”了匹配项。

于 2012-07-15T15:10:41.253 回答
0

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

这个 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 与我们选择表达式的方法步骤的 RoomId 进行比较。因此,链接的名称被复制到房间下。没有 xsl:if,没有 xsl:for-each,没有变量。所有这些都可以在 select 表达式中使用 current() 函数来实现。

于 2012-07-15T14:55:41.730 回答
0

你的问题是上下文。if条件失败,因为它是从节点的上下文运行的,因此MethodXPath 表达式../RoomID正在寻找. 没有这样的节点。RoomIDdsInventory

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

您可以运行它并在此 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>
于 2012-07-15T14:39:10.303 回答