2014-12-03 97 views
0

在XSL转换中,有两件事我一直无法弄清楚。 在源XML中删除属性和空元素

<Network> 
    <Hosts> 
    <Host modelId="1" name="H1"> 
     <LinPorts> 
     <LinPort name="Port3" speed="100" parent="H1"/> 
     </LinPorts> 
     <CanPorts/> 
     <EthernetPorts> 
     <EthernetPort name="Port1" speed="100" parent="H1"/> 
     <EthernetPort name="Port2" speed="100" parent="H1"/> 
     </EthernetPorts> 
    </Host> 
    <Host modelId="1" name="H2"> 
     <CanPorts> 
     <CanPort name="Port2" speed="100" parent="H2"/> 
     </CanPorts> 
     <EthernetPorts> 
     <EthernetPort name="Port1" speed="100" parent="H3"/> 
     </EthernetPorts> 
    </Host> 
    <Host modelId="1" name="lin"> 
     <LinPorts> 
     <LinPort name="Port1" speed="10" parent="lin"/> 
     <LinPort name="Port2" speed="100" parent="H2"/> 
     <LinPort name="Port3" speed="100" parent="lin"/> 
     </LinPorts> 
    </Host> 
    </Hosts> 
    <DataFrames> 
    <DataFrame bitSize="21" name="greasd" offset="0.021" period="0.021" prio="0"> 
     <Path name="greasd-S5" parent="greasd"> 
     <Node name="H1" sequenceNumber="1" parent="greasd-S5"/> 
     <Node name="S5" sequenceNumber="2" parent="greasd-S5"/> 
     </Path> 
    </DataFrame> 
    <DataFrame bitSize="23" name="hytdsg" offset="0.423" period="0.423" prio="0"> 
     <Path name="hytdsg-H1" parent="hytdsg"> 
     <Node name="H2" sequenceNumber="1" parent="hytdsg-H1"/> 
     <Node name="S5" sequenceNumber="2" parent="hytdsg-H1"/> 
     <Node name="H1" sequenceNumber="3" parent="hytdsg-H1"/> 
     </Path> 
    </DataFrame> 
    </DataFrames> 
</Network> 

一些子节点被错误地放置。我正在使用@parent属性来正确放置它们。这适用于下面的XSLT。

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

<!-- Copy all nodes (that do not get a better match) as they are --> 
<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Host"> 
    <xsl:variable name="hostname" select="@name"/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <LinPorts> 
      <xsl:apply-templates select="//LinPorts/LinPort[@parent=$hostname]"> 
       <xsl:sort select="@name" data-type="text" /> 
      </xsl:apply-templates> 
     </LinPorts> 
     <CanPorts> 
      <xsl:apply-templates select="//CanPorts/CanPort[@parent=$hostname]"> 
       <xsl:sort select="@name" data-type="text" /> 
      </xsl:apply-templates> 
     </CanPorts> 
     <EthernetPorts> 
      <xsl:apply-templates 
       select="//EthernetPorts/EthernetPort[@parent=$hostname]"> 
       <xsl:sort select="@name" data-type="text" /> 
      </xsl:apply-templates> 
     </EthernetPorts> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="DataFrame"> 
    <xsl:variable name="framename" select="@name"/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates select="//Path[@parent=$framename]"> 
      <xsl:sort select="@name" data-type="text" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Path"> 
    <xsl:variable name="pathname" select="@name"/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates select="//Node[@parent=$pathname]"> 
      <xsl:sort select="@sequenceNumber" data-type="text" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

<!-- Do not save attributes parent and ID for child elements --> 
<xsl:template match="CanPort|LinPort|EthernetPort|Node"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*[not(name()='parent') and not(name()='id')]"> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
  1. 我还创建是空的(CanPorts,LinPorts,EthernetPorts)元素。我如何摆脱这些?
  2. 我想摆脱@parent属性。除Path之外,我已设法为所有元素进行此操作。我如何摆脱Path.parent?

回答

1

对于点1,你可以使用一个xsl:if创建LinPorts,CanPorts和EthernetPorts元素之前 而对于2检查LinPort,CanPort和EthernetPort的计数,加上匹配@parent和什么也不做另一个模板:

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

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

<xsl:template match="Host"> 
    <xsl:variable name="hostname" select="@name"/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:if test="count(//LinPorts/LinPort[@parent=$hostname]) != 0"> 
      <LinPorts> 
       <xsl:apply-templates select="//LinPorts/LinPort[@parent=$hostname]"> 
        <xsl:sort select="@name" data-type="text" /> 
       </xsl:apply-templates> 
      </LinPorts> 
     </xsl:if> 
     <xsl:if test="count(//CanPorts/CanPort[@parent=$hostname]) != 0"> 
      <CanPorts> 
       <xsl:apply-templates select="//CanPorts/CanPort[@parent=$hostname]"> 
        <xsl:sort select="@name" data-type="text" /> 
       </xsl:apply-templates> 
      </CanPorts> 
     </xsl:if> 
     <xsl:if test="count(//EthernetPorts/EthernetPort[@parent=$hostname]) != 0"> 
      <EthernetPorts> 
       <xsl:apply-templates 
      select="//EthernetPorts/EthernetPort[@parent=$hostname]"> 
        <xsl:sort select="@name" data-type="text" /> 
       </xsl:apply-templates> 
      </EthernetPorts> 
     </xsl:if> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="DataFrame"> 
    <xsl:variable name="framename" select="@name"/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates select="//Path[@parent=$framename]"> 
      <xsl:sort select="@name" data-type="text" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Path"> 
    <xsl:variable name="pathname" select="@name"/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates select="//Node[@parent=$pathname]"> 
      <xsl:sort select="@sequenceNumber" data-type="text" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

<!-- Do not save attributes parent and ID for child elements --> 
<xsl:template match="CanPort|LinPort|EthernetPort|Node"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 
<!-- This template matches @parent and @id and does nothing --> 
<xsl:template match="@parent | @id"/> 
</xsl:stylesheet>