循环中打印XSLT

时间:2017-11-06 03:56:56

标签: xml xslt

我需要使用XSLT将XML(1.0)转换为TXT以供人们阅读

并在【template match =“/”>】区域内进行

这是我的XML:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="OutputFile.xslt"?>
<File>
    <Header>
      <A><![CDATA[Order]]></A>
      <B><![CDATA[Add]]></B>
      <C><![CDATA[BN]]></C>
      <D><![CDATA[Comment]]></D>
      <E><![CDATA[Base]]></E>
    </Header>
    <Data>
      <row A="1" B="X" C="11.00000" D="" E="0"/>
      <row A="2" B="X" C="5.00000" D="" E="0"/>
      <row A="3" B="X" C="11.00000" D="" E="0"/>
    </Data>
    <Table>
      <Bin Name ="A1" BinNum="1" BinDesc="Type_S" End=""/>
      <Bin Name ="A4" BinNum="2" BinDesc="Type_AC3" End=""/>
      <Bin Name ="A9" BinNum="3" BinDesc="Type_E5" End=""/>
      <Bin Name ="A12" BinNum="4" BinDesc="Type_E5" End=""/>
      <Bin Name ="A14" BinNum="5" BinDesc="Type_E5" End=""/>
      <Bin Name ="A22" BinNum="6" BinDesc="Type_E5" End=""/>
      <Bin Name ="A23" BinNum="7" BinDesc="Type_E6" End=""/>
      <Bin Name ="A24" BinNum="8" BinDesc="Type_AF3C" End=""/>
      <Bin Name ="A56" BinNum="9" BinDesc="Type_none" End=""/>
      <Bin Name ="A57" BinNum="10" BinDesc="Type_defalt" End=""/>
      <Bin Name ="A70" BinNum="11" BinDesc="Type_auto" End=""/>
      <Bin Name ="A71" BinNum="0" BinDesc="Type_mau" End=""/>
    </Table>
</File>

我需要搜索[BN]的Header,知道它位于C, 然后搜索attritube C的数据/行, 最后使用此值来比较Table中的BinNum并打印相应的类型

这是我的XSLT

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:fn="http://www.w3.org/2006/xpath-functions">
  <xsl:output method="text" indent="yes"/>
  <xsl:template match="/">

    <xsl:text>What I want to print is the value of position 11,5,11</xsl:text>
          <xsl:text>&#10;</xsl:text>
          <xsl:value-of select="/File/Table/Bin[position()=11]/@*[position()=3]"/>
          <xsl:text>&#10;</xsl:text>
          <xsl:value-of select="/File/Table/Bin[position()=5]/@*[position()=3]"/>
          <xsl:text>&#10;</xsl:text>
          <xsl:value-of select="/File/Table/Bin[position()=11]/@*[position()=3]"/>
          <xsl:text>&#10;</xsl:text>


    <xsl:variable name="BN">
      <xsl:choose>
        <xsl:when test="count(/File/Header/*[text()='BN']) = 1">
          <xsl:value-of select="count(/File/Header/*[text()='BN']/preceding-sibling::*) + 1"/>
        </xsl:when>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="BN_location">
      <xsl:for-each select="/File/Data/row">
        <xsl:for-each select="@*">
            <xsl:if test="position() =$BN">
              <xsl:value-of select="number(.)"/>
            </xsl:if>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:variable>

    <xsl:text>&#10;</xsl:text>
    <xsl:text>But so far I can only print the number 11,5,11 ~~so sad!</xsl:text>
    <xsl:text>&#10;</xsl:text>
    <xsl:for-each select="/File/Data/row">
      <xsl:for-each select="@*">
        <xsl:if test="position() =$BN">
          <xsl:value-of select="number(.)"/>
          <xsl:text>;</xsl:text>
        </xsl:if>
      </xsl:for-each>

      <xsl:value-of select="/File/Table/Bin[position()=$BN_location]/@*[position()=2]"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>

  </xsl:template>
</xsl:stylesheet>

输出是

What I want to print is the value of position 11,5,11
Type_auto
Type_E5
Type_auto

But so far I can only print the number 11,5,11 ~~so sad!
11;
5;
11;

任何帮助? THX!

3 个答案:

答案 0 :(得分:1)

您可以按如下方式获得所需的输出。首先使用BN函数在text()中找到包含local-name()值的节点。

<xsl:variable name="BNNode" select="local-name(/File/Header/*[text() = 'BN'])" />

使用此节点,循环遍历<row>的属性,使属性名称与节点名称匹配。

<xsl:for-each select="/File/Data/row/@*[local-name() = $BNNode]">

循环遍历<Bin>所有@BinNum匹配从上述for-each循环接收的属性值的所有内容。

<xsl:for-each select="/File/Table/Bin[@BinNum = number($attrVal)]">

选择并打印@BinDesc

的值

完整的XSLT如下所示。

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

    <xsl:variable name="BNNode" select="local-name(/File/Header/*[text() = 'BN'])" />
    <xsl:template match="/">
        <xsl:for-each select="/File/Data/row/@*[local-name() = $BNNode]">
            <xsl:variable name="attrVal" select="." />
            <xsl:for-each select="/File/Table/Bin[@BinNum = number($attrVal)]">
                <xsl:value-of select="@BinDesc" />
                <xsl:text>&#10;</xsl:text>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

输出

Type_auto
Type_E5
Type_auto

答案 1 :(得分:1)

这是(在我看来)使用键执行此操作的优雅方式:

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

  <xsl:key name="rowAttribsByName" match="Data/row/@*" use="name()"/>
  <xsl:key name="binsByNum" match="Table/Bin" use="@BinNum"/>

  <xsl:template match="/File">
    <xsl:variable name="targetAttribName" select="name(Header/*[. = 'BN'])" />

    <xsl:for-each select="key('rowAttribsByName', $targetAttribName)">
      <xsl:value-of select="key('binsByNum', number())/@BinDesc"/>
      <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

在样本输入上运行时,结果为:

Type_auto
Type_E5
Type_auto

答案 2 :(得分:0)

这是我使用嵌套for-each的解决方案。 我希望这会对你有所帮助。

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:fn="http://www.w3.org/2006/xpath-functions">
  <xsl:output method="text" indent="yes"/>

  <xsl:template match="/">

    <xsl:variable name="BN_location" select="name(/File/Header/*[text()='BN'])"/> 

    <xsl:for-each select="/File/Data/row/@*[local-name()=$BN_location]">
        <xsl:variable name="BN_attr" select="." />
        <xsl:for-each select="/File/Table/Bin[@BinNum = round($BN_attr)]">
            <xsl:value-of select="./@BinDesc"/>
            <xsl:text>|</xsl:text>
        </xsl:for-each>
    </xsl:for-each>

  </xsl:template>
</xsl:stylesheet>