代码之家  ›  专栏  ›  技术社区  ›  Brian Arthur

XSLT从另一个上下文获取信息

  •  0
  • Brian Arthur  · 技术社区  · 7 年前

    我试图引用一本书的标题和作者元素,同时使用for-each循环遍历每个书架。 这是我的XML:

    <DOC>
      <BOOKS>
        <BOOK ID="1234">
          <TITLE>Intro to XSLT</TITLE>
          <AUTHOR>Junior Writer</AUTHOR>
        </BOOK>
        <BOOK ID="1235">
          <TITLE>Advanced XSLT</TITLE>
          <AUTHOR>Senior Writer</AUTHOR>
        </BOOK>
      </BOOKS>
      <CABINET>
        <SHELF>
          <NAME>Top</NAME>
          <BOOK ID="1234"/>
          <BOOK ID="1235"/>
        </SHELF>
        <SHELF>
          <NAME>Middle</NAME>
          <BOOK ID="1235"/>
        </SHELF>
      </CABINET>
    </DOC>
    

    在经历了许多黑暗中拍摄的变化之后,我正在尝试当前的XSL,但不起作用:

    <xsl:for-each select="CABINET/SHELF">
        <xsl:value-of select="NAME"> Shelf:
        <xsl:for-each select="BOOK">
          <xsl:value-of select="/BOOKS/BOOK[@ID=current()/@ID]/TITLE"/> by
          <xsl:value-of select="/BOOKS/BOOK[@ID=current()/@ID]/AUTHOR"/>
        </xsl:for-each>
    
    </xsl:for-each>
    

    我希望它显示为:

    Top Shelf:
    Intro to XSLT by
    Junior Writer
    Advanced XSLT by
    Senior Writer
    
    Middle Shelf:
    Advanced XSLT by
    Senior Writer
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   Daniel Haley    7 年前

    我对你的例子有点困惑。首先,您的XML输入不是 well-formed ;您没有一个根元素。此外,在XSLT代码段中,您可以选择 DOCUMENT 元素,但该元素在您的输入中不存在。(更不用说你错过了 = 在所有 select 属性。)

    否则,您的使用方法 current() 进行比较 ID 属性正确且有效。

    另一种选择是使用 a key

    以下是两种方法的示例。如果在将这些应用于实际XML时仍然存在问题,请更新问题中的XML,我可以更新我的答案。

    XML输入 (更新为格式良好)

    <DOC>
        <BOOKS>
            <BOOK ID="1234">
                <TITLE>Intro to XSLT</TITLE>
                <AUTHOR>Junior Writer</AUTHOR>
            </BOOK>
            <BOOK ID="1235">
                <TITLE>Advanced XSLT</TITLE>
                <AUTHOR>Senior Writer</AUTHOR>
            </BOOK>
        </BOOKS>
        <CABINET>
            <SHELF>
                <NAME>Top</NAME>
                <BOOK ID="1234"/>
                <BOOK ID="1235"/>
            </SHELF>
            <SHELF>
                <NAME>Middle</NAME>
                <BOOK ID="1235"/>
            </SHELF>
        </CABINET>
    </DOC>
    

    选项#1 ( fiddle )

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="text"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:template match="/*">
        <xsl:for-each select="CABINET/SHELF">
          <xsl:if test="position() > 1"><xsl:text>&#xA;&#xA;</xsl:text></xsl:if>      
          <xsl:value-of select="NAME"/>
          <xsl:text> Shelf:&#xA;</xsl:text> 
          <xsl:for-each select="BOOK">
            <xsl:if test="position() > 1"><xsl:text>&#xA;</xsl:text></xsl:if>
            <xsl:value-of select="/DOC/BOOKS/BOOK[@ID = current()/@ID]/TITLE"/>
            <xsl:text> by&#xA;</xsl:text> 
            <xsl:value-of
              select="/DOC/BOOKS/BOOK[@ID = current()/@ID]/AUTHOR"/>
          </xsl:for-each>
        </xsl:for-each>
      </xsl:template>
    
    </xsl:stylesheet>
    

    选项#2 ( fiddle )

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="text"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:key name="books" match="BOOK" use="@ID"/>
    
      <xsl:template match="/*">
        <xsl:for-each select="CABINET/SHELF">
          <xsl:if test="position() > 1"><xsl:text>&#xA;&#xA;</xsl:text></xsl:if>      
          <xsl:value-of select="NAME"/>
          <xsl:text> Shelf:&#xA;</xsl:text> 
          <xsl:for-each select="BOOK">
            <xsl:if test="position() > 1"><xsl:text>&#xA;</xsl:text></xsl:if>
            <xsl:value-of select="key('books',@ID)/TITLE"/>
            <xsl:text> by&#xA;</xsl:text> 
            <xsl:value-of select="key('books',@ID)/AUTHOR"/>
          </xsl:for-each>
        </xsl:for-each>
      </xsl:template>
    
    </xsl:stylesheet>
    

    这两个选项都会产生以下输出:

    Top Shelf:
    Intro to XSLT by
    Junior Writer
    Advanced XSLT by
    Senior Writer
    
    Middle Shelf:
    Advanced XSLT by
    Senior Writer
    

    您还可以使用推式样式而不是拉式样式,这样在样式表变得更复杂的情况下更容易扩展。。。

    选项#2推送样式 ( fiddle )

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="text"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:key name="books" match="BOOK" use="@ID"/>
    
      <xsl:template match="/DOC">
        <xsl:apply-templates select="CABINET/SHELF"/>
      </xsl:template>
    
      <xsl:template match="SHELF[position() > 1]">
        <xsl:text>&#xA;&#xA;</xsl:text>
        <xsl:apply-templates/>
      </xsl:template>
    
      <xsl:template match="NAME">
        <xsl:apply-templates/>
        <xsl:text> Shelf:</xsl:text>     
      </xsl:template>
    
      <xsl:template match="BOOK">
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="key('books',@ID)/TITLE"/>
        <xsl:text> by&#xA;</xsl:text>
        <xsl:apply-templates select="key('books',@ID)/AUTHOR"/>
      </xsl:template>
    
    </xsl:stylesheet>