XSLT基于多个条件显示XML

时间:2016-07-13 16:52:55

标签: xml xslt

<Data>
<Record Id="1826155" username="BobDylan" >
    <ART id="121028890624">
        <TYPE>Song</TYPE>
        <AUTH>
            <AUTHOR_ID>1826155</AUTHOR_ID>
            <FNAME>Bob</FNAME>
            <LNAME>Dylan</LNAME>
            <HIDE/>
        </AUTH>
        <AUTH>
            <AUTHOR_ID>175782</AUTHOR_ID>
            <FNAME>Frank</FNAME>
            <LNAME>Sinatra</LNAME>
            <HIDE>true</HIDE>
        </AUTH>
        <STATUS>Published</STATUS>
        <TITLE>A Cool Song </TITLE>
    </ART>
    <ART id="123840712342">
        <TYPE>Song</TYPE>
        <AUTH>
            <AUTHOR_ID>1826155</AUTHOR_ID>
            <FNAME>Bob</FNAME>
            <LNAME>Dylan</LNAME>
            <HIDE>true</HIDE>
        </AUTH>
        <AUTH>
            <AUTHOR_ID>175782</AUTHOR_ID>
            <FNAME>Tom</FNAME>
            <LNAME>Waits</LNAME>
        </AUTH>
        <STATUS>Published</STATUS>
        <TITLE>New Song</TITLE>
    </ART>
    <ART id="123840737280">
        <TYPE>Book</TYPE>
        <AUTH>
            <AUTHOR_ID>1826155</AUTHOR_ID>
            <FNAME>Bob</FNAME>
            <LNAME>Dylan</LNAME>
            <HIDE/>
        </AUTH>
        <AUTH>
            <AUTHOR_ID>175782</AUTHOR_ID>
            <FNAME>Tom</FNAME>
            <LNAME>Wolfe</LNAME>
        </AUTH>
        <STATUS>Accepted</STATUS>
        <TITLE>New Book</TITLE>
    </ART>
</Record>
</Data>

我尝试通过选择符合以下条件的Song节点来转换上述XML:

  1. 状态=&#39;已发布&#39;
  2. 如果与数据/记录/ @ Id匹配的/ AUTH / AUTHOR_ID的AUTH / HIDE值为true,则不显示ART / TYPE(在这种情况下,Id = 1826155)
  3. 所需的XML输出应包括Type,所有作者和标题。第二个歌曲类型在此示例中隐藏(因为主要作者的HIDE = true):

    <h3>Songs</h3>
    <div>
     <ul>
      <li>Bob Dylan, Frank Sinatra; A Cool Song</li>
     </ul>
    </div>
    

    我开始尝试每个人,但发现我无法处理与Record Id不匹配的作者。根据建议,我相信这是使用模板最好的。我有一些XSLT无法正常工作,而是显示所有数据而不是子集。

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
      <xsl:output method="html" encoding="utf-8" />
      <xsl:variable name="userId" select="dm:Data/dm:Record/@userId"/>
    
        <xsl:template match="/Data/Record/ART[TYPE='Song']">
       <xsl:apply-templates select= "/Data/Record/ART[CONTYPE='Song']/AUTH[AUTHOR_ID = $userId]" />
      </xsl:template>
    
     <xsl:template match="/Data/Record/ART[TYPE='Song']">
        <xsl:apply-templates select= "/Data/Record/ART[TYPE='Song']/AUTH[/STATUS = 'PUBLISHED']" />
     </xsl:template>
    
     <xsl:template match="/Data/Record/ART[TYPE='Song']">
          <xsl:value-of select="./FNAME"/> <xsl:text> </xsl:text>
          <xsl:value-of select="./LNAME"/> <xsl:text> </xsl:text>
          <xsl:value-of select="./TITLE"/> <xsl:text> </xsl:text>
     </xsl:template>
    
    </xsl:stylesheet>
    

2 个答案:

答案 0 :(得分:1)

  

我开始尝试每个人,但发现我无法应对   显示与记录ID不匹配的作者。

为什么不呢?

<xsl:for-each select="/Data/Record/ART/AUTH[AUTHOR_ID = ancestor::Record/@Id]">

将仅选择AUTHOR_ID与其记录的ID匹配的作者。

要将其缩小为仅发布歌曲的作者,您可以使用:

<xsl:for-each select="/Data/Record/ART[TYPE = 'Song' and STATUS = 'Published']/AUTH[AUTHOR_ID = ancestor::Record/@Id]">

进一步排除隐藏的作者:

<xsl:for-each select="/Data/Record/ART[TYPE = 'Song' and STATUS = 'Published']/AUTH[AUTHOR_ID = ancestor::Record/@Id and not(HIDE='true')]">

当然,您也可以在xsl:apply-templates使用相同的谓词。

加了:

响应您的修改:

我仍然觉得这些要求令人困惑。我你想做这样的事情:

XSLT 1.0

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

<xsl:template match="/Data">
    <h3>Songs</h3>
    <div>
        <xsl:for-each select="Record/ART[TYPE = 'Song' and STATUS = 'Published' and not(parent::Record/@Id = AUTH[HIDE='true']/AUTHOR_ID)]">
            <ul>
                <li>
                    <xsl:for-each select="AUTH">
                        <xsl:value-of select="FNAME"/> 
                        <xsl:text> </xsl:text>
                        <xsl:value-of select="LNAME"/> 
                        <xsl:if test="position()!=last()">
                            <xsl:text>, </xsl:text>
                        </xsl:if>
                    </xsl:for-each>
                    <xsl:text>; </xsl:text>
                    <xsl:value-of select="TITLE"/> 
                </li>
            </ul>
        </xsl:for-each>
    </div>
</xsl:template>

</xsl:stylesheet>

这将选择满足所有这些条件的每种ART:

  1. TYPE =&#39; Song&#39 ;;

  2. 状态=&#39;已发布&#39;;

  3. 它的作者都没有(a)AUTHOR_ID与祖先的记录ID 匹配和(b)HIDE =&#39; True&#39;。< / p>

  4. 对于每一个这样的ART,它的所有作者都会被列出,以及ART的标题:

    <强>结果

    <h3>Songs</h3><div>
      <ul>
        <li>Bob Dylan, Frank Sinatra; A Cool Song </li>
      </ul>
    </div>  
    

答案 1 :(得分:1)

这应该有用。

第一个匹配找到记录并将id存储在recId变量中。然后,它使用此变量将ART上的匹配应用于您指定的id和其他参数。您提供的示例XML没有名称空间,因此我将其关闭。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <xsl:output method="html" encoding="utf-8" />

<xsl:template match="/Data/Record">
   <xsl:variable name="recId" select="@Id"/>

   <xsl:apply-templates select="ART[TYPE='Song' and STATUS='Published' and AUTH/AUTHOR_ID=$recId and AUTH/HIDE!='true']" />
</xsl:template>

 <xsl:template match="Data/Record/ART">
   <xsl:value-of select="TITLE"/>
   <xsl:value-of select="AUTH/FNAME"/>
   <xsl:value-of select="AUTH/LNAME"/>

 </xsl:template>

</xsl:stylesheet>