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

时间:2018-04-20 16:03:29

标签: xml xslt xslt-1.0

我正在尝试引用BOOK的TITLE和AUTHOR元素,同时使用for-each循环遍历每个SHELF。 这是我的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 个答案:

答案 0 :(得分:0)

我对你的例子感到有些困惑。首先,您的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

你也可以使用push-style而不是pull-style,这样如果/当它变得更复杂时,你的样式表会更容易扩展...

选项#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>