2015-06-06 163 views
0

我试图根据其他节点的值更新一个节点的属性。基于其他节点的值更新节点值

我的XML:

<Report> 
    <Action rID="T4"> 
    <Step rID="T5"> 
     <Obj ><![CDATA[BAR]]></Obj> 
     <Details ><![CDATA[Total files to compare = 1]]></Details> 
     <Time><![CDATA[05/06/2015 - 20:41:07]]></Time> 
     <TimeTick>1433533267</TimeTick> 
     <NodeArgs eType="User" icon="5" nRep="8" Source="Action1" status="Done" SourceLine="-1" > 
    <Disp><![CDATA[BAR]]></Disp> 
     </NodeArgs> 
    </Step> 
    <Step rID="T7"> 
     <Obj ><![CDATA[File 1 : Passed]]></Obj> 
     <Details ><![CDATA[Baseline = C:\Baseline\BAR\1759982021.xml 
     Outbound = C:\Outbound\BAR\1759982021.xml]]></Details> 
     <Time><![CDATA[05/06/2015 - 20:41:07]]></Time> 
     <TimeTick>1433533267</TimeTick> 
     <NodeArgs eType="User" icon="5" nRep="10" status="Passed" Source="Action1" SourceLine="-1" > 
    <Disp><![CDATA[File 1 : Passed]]></Disp> 
     </NodeArgs> 
    </Step> 
    <Step rID="T9"> 
     <Obj ><![CDATA[PASS]]></Obj> 
     <Details ><![CDATA[]]></Details> 
     <Time><![CDATA[05/06/2015 - 20:41:08]]></Time> 
     <TimeTick>1433533268</TimeTick> 
     <NodeArgs eType="User" icon="5" nRep="12" status="Information" Source="Action1" SourceLine="-1" > 
    <Disp><![CDATA[PASS]]></Disp> 
     </NodeArgs> 
    </Step> 

    <Step rID="T71"> 
     <Obj><![CDATA[MSP]]></Obj> 
     <Details><![CDATA[Total files to compare = 1]]></Details> 
     <Time><![CDATA[06/06/2015 - 20:58:02]]></Time> 
     <TimeTick>1433620682</TimeTick> 
     <NodeArgs eType="User" icon="5" nRep="74" Source="Action1" SourceLine="-1"> 
     <Disp><![CDATA[MSP]]></Disp> 
     </NodeArgs> 
    </Step> 
    <Step rID="T72"> 
     <Obj><![CDATA[File 1 : Passed]]></Obj> 
     <Details><![CDATA[Baseline = C:\Baseline\MSP\G82164M1225983TN000073914GEU9.xml 
    Outbound = C:\Outbound\MSP\G82164M1225983TN000073914GEU9.xml]]> 
    </Details> 
     <Time><![CDATA[06/06/2015 - 20:58:02]]></Time> 
     <TimeTick>1433620682</TimeTick> 
     <NodeArgs eType="User" icon="5" nRep="75" status="Passed" Source="Action1" SourceLine="-1"> 
     <Disp><![CDATA[File 1 : Failed]]></Disp> 
     </NodeArgs> 
    </Step> 
    <Step rID="T73"><Obj> <![CDATA[FAIL]]></Obj> 
     <Details><![CDATA[]]></Details> 
     <Time><![CDATA[06/06/2015 - 20:58:02]]></Time> 
     <TimeTick>1433620682</TimeTick> 
     <NodeArgs eType="User" icon="5" nRep="76" status="Information" Source="Action1" SourceLine="-1"> 
     <Disp><![CDATA[FAIL]]></Disp> 
     </NodeArgs> 
    </Step> 
    </Action> 
</Report> 

我的产出将是HTML。在我的XML中,可能有无数个步骤块。对于每个步骤块,只有一个完成和信息步骤。因此,对于每个完成步骤块,Information步骤会通知该块是否为PASS/FAIL。因此,我想将XML转换为XML,然后转换为HTML,而不对CDATA进行硬编码。

  • if Step/NodeArgs[@status='Information']/Disp = PASS then Step/NodeArgs[@status='Done']/Disp应该是PASSBAR

即使我可以将Status = Done更改为Status = PASSDone,那也是有用的。

我的XSL到目前为止

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

<xsl:template match="/Report/Action"> 
    <html> 
     <head> 
     <style type="text/css"> 
      body { font-family:Tahoma; font-size:9pt; } 
      h2 {color: #b48608; font-style: italic; text-align: center; text-decoration: underline;} 
      table { table-layout: auto; } 
      table, th, td { font-family:Tahoma; font-size:9pt; padding:5px; border-collapse:collapse; vertical-align:top; border:1px solid black; white-space:nowrap; } 
      th, tr.Venue { text-align:left; background-color:#D3D3D3; font-weight: bold; } 
      td.Passed { font-size:11pt; color:Green; text-align:center; } 
      td.Failed { font-size:11pt; color:Red; text-align:center; } 
      tr.Passed { background-color:#AAEEAA; font-weight:bold; } 
      tr.Failed { background-color:#FFAAAA; font-weight:bold; } 
     </style> 
     </head> 
     <body> 
     <table> 
      <th>Venues</th> 
      <th>Status</th> 
      <xsl:variable name="VenueTestStatus" select="Step/NodeArgs[@status='Information']/Disp"/> 
      <xsl:variable name="VenueName" select="Step/NodeArgs[@status='Done']/Disp"/> 
      <xsl:for-each select="$VenueTestStatus"> 
      <xsl:variable name="i" select="position()"/> 
      <tr> 
       <xsl:if test="$VenueTestStatus[$i]='PASS'"> 
       <xsl:attribute name="class">Passed</xsl:attribute> 
       </xsl:if> 
       <xsl:if test="$VenueTestStatus[$i]='FAIL'"> 
       <xsl:attribute name="class">Failed</xsl:attribute> 
       </xsl:if>    
       <td> 
       <a> 
        <xsl:attribute name="href"> 
        <xsl:value-of select="concat('#',$VenueName[$i])" /> 
        </xsl:attribute> 
        <xsl:value-of select="$VenueName[$i]" /> 
       </a> 
       </td> 
       <td> 
       <xsl:value-of select="$VenueTestStatus[$i]" /> 
       </td> 
      </tr> 
      </xsl:for-each> 
     </table> 

     <br/> 
     <hr/> 
     <br/> 

     <table> 
      <xsl:for-each select="Step"> 
       <xsl:if test="NodeArgs/@status != 'Information'"> 
       <tr> 
        <xsl:variable name="IsVenueRow"> 
        <xsl:value-of select="NodeArgs/Disp" disable-output-escaping="no"/> 
        </xsl:variable> 
        <xsl:if test="not(starts-with($IsVenueRow, 'File'))"> 
        <xsl:attribute name="class">Venue</xsl:attribute> 
        </xsl:if> 

        <td> 
        <xsl:variable name="StatusSymbol"> 
         <xsl:value-of select="NodeArgs/@status" disable-output-escaping="no"/> 
        </xsl:variable> 
        <xsl:attribute name="class"> 
         <xsl:value-of select="$StatusSymbol" /> 
        </xsl:attribute> 
        <xsl:choose> 
         <xsl:when test="NodeArgs/@status = 'Passed'"> 
         <xsl:text>&#10004;</xsl:text> 
         </xsl:when> 
         <xsl:when test="NodeArgs/@status = 'Failed'"> 
         <xsl:text>&#10008;</xsl:text> 
         </xsl:when> 
        </xsl:choose> 
        </td> 

        <td> 
        <xsl:choose> 
         <xsl:when test="not(starts-with($IsVenueRow, 'File'))"> 
         <a> 
          <xsl:attribute name="name"> 
          <xsl:value-of select="$IsVenueRow" /> 
          </xsl:attribute> 
          <xsl:value-of select="$IsVenueRow" /> 
         </a> 
         </xsl:when> 
         <xsl:otherwise> 
         <xsl:value-of select="$IsVenueRow" /> 
         </xsl:otherwise> 
        </xsl:choose> 
        </td> 
       </tr> 
      </xsl:if> 
      </xsl:for-each> 
     </table> 
     </body> 
    </html> 
    </xsl:template> 

</xsl:stylesheet> 

回答

0

我想你想的身份变换,然后建立<Disp/>根据您的标准:

<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="Disp"> 
    <Disp> 
     <xsl:choose> 

    <xsl:when test="../../NodeArgs[@status='Information']"> 
     PASS 
    </xsl:when> 

    <xsl:when test="../../NodeArgs[@status='Done']"> 
     PASSBAR 
    </xsl:when> 

    <xsl:otherwise> 
     <!-- Copy this (Disp) tree as is --> 
     <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:otherwise> 

     </xsl:choose> 
    </Disp> 
    </xsl:template> 
</xsl:stylesheet> 

这是恒等变换部分:

<xsl:template match="node()|@*" > 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

本身,它只会复制原始文档。

通过匹配上<Disp/>

<xsl:template match="Disp"> 

我们可以只复制<Disp/>停止处理器和插话我们自己的版本:

<Disp> 
    <xsl:choose> 
    <xsl:when test="..."> 

,如果没有我们的<xsl:when/>条件相匹配,我们开始身份再次变换:

<xsl:otherwise> 
    <!-- Copy this (Disp) tree as is --> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:otherwise> 

继续执行节点/属性 - 节点/属性复制。

1

一个可能的XSL转换:

<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="Action[Step/NodeArgs[@status='Information']/Disp = 'PASS']/Step/NodeArgs[@status='Done']/Disp"> 
     <xsl:copy> 
      <xsl:text><![CDATA[PASSBAR]]></xsl:text> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

简要说明:

  1. 身份模板(<xsl:template match="node()|@*">)复制的每一个节点,因为它是在源XML
  2. 其他模板覆盖身份模板规则。它正在选择Step/NodeArgs[@status='Done']/Disp元素,其中相应的Step/NodeArgs[@status='Information']/Disp元素值等于"PASS",并用输出XML中的<![CDATA[PASSBAR]]>替换选定的Disp元素值。
+0

我的输出是HTML。在我的XML中,可能有许多“步骤”块。对于每个步骤块,只有一个“完成”和“信息”步骤。因此,对于每个完成步骤块,Information步骤会通知该块是否为PASS/FAIL。因此,我想将XML转换为XML,然后转换为HTML,而不对CDATA进行硬编码。 –

+0

我已经更新了我的代码并测试了xml –

+0

@PankajJaju我可以看到,从您的XML示例中,我的答案中的XSLT工作方式相同。 – har07