XSLT将复杂的实时XML转换为有意义的扁平XML

时间:2014-03-07 09:54:30

标签: xml xslt xpath

我对XSLT有疑问。我是新手。通过论坛阅读并尝试获取所需格式化的XML格式输出。

如您所见,根据$<DataSources>代码属性TYPEID,其子NODES会有所不同。

我想在这里实现的是

  1. FLATTEN XML的层次结构
  2. out put some TAGS
  3. <expression>之类的TAGS转换为包含其他子节点或标签而不是TEXT()值的TAGS到此格式的表达式

    (AND)..((((EventDisplayNumber)(等于)(823)))...... ..依此类推

  4. 到目前为止,我只能将所有属性转换为ELEMENTS,作为展平XML的第一步。

    下一步是打破层次结构并将深层嵌套的XML标签转换为数学符号中的符号表达式。

    第三个是从前一个输出中选择所需的NODES。

    请提出建议或帮助,因为我完全不知道如何继续下去。

    INPUT ::

    <Rule ID="SpaceLeftPercent." Enabled="true" Target="DBFileGroup"    >
        <Category>PerformanceCollection</Category> 
        <DataSources>
            <DataSource ID="DS" TypeID="DBFileGroupSizeOptimizedPerfProvider">
                <IntervalSeconds>900</IntervalSeconds>
                <SyncTime /> 
                <ConnectionString> ConnectionString$</ConnectionString>
                <ServerName> NetworkName$</ServerName>
                <SqlInstanceName> InstanceName$</SqlInstanceName>
                <ObjectName> PerformanceCounterObject$ : Database : File Group</ObjectName>
                <CounterName>DB File Group Allocated Space Left (%)</CounterName>
                <InstanceName> GroupName$</InstanceName>
                <DatabaseName> DatabaseName$</DatabaseName>
                <DBFileGroupId>GroupID$</DBFileGroupId>
                <Value>$Data/Property[@Name='FreeSpaceAutoGrowPercent']$</Value>
                <Tolerance>10</Tolerance>
                <ToleranceType>Absolute</ToleranceType>
                <MaximumSampleSeparation>4</MaximumSampleSeparation>
                <TimeoutSeconds>300</TimeoutSeconds>
            </DataSource>
        </DataSources> 
    </Rule>
    

    <Rule ID=" id823" Enabled="true"  ConfirmDelivery="true" Remotable="true" >
        <Category>EventCollection</Category>
        <DataSources>
            <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.EventProvider">
                <ComputerName>NetworkName$</ComputerName>
                <LogName>Application</LogName>
                <Expression>
                    <And>
                        <Expression>
                            <SimpleExpression>
                                <ValueExpression>
                                    <XPathQuery Type="UnsignedInteger">EventDisplayNumber</XPathQuery>
                                </ValueExpression>
                                <Operator>Equal</Operator>
                                <ValueExpression>
                                    <Value Type="UnsignedInteger">823</Value>
                                </ValueExpression>
                            </SimpleExpression>
                        </Expression>
                        <Expression>
                            <SimpleExpression>
                                <ValueExpression>
                                    <XPathQuery Type="String">PublisherName</XPathQuery>
                                </ValueExpression>
                                <Operator>Equal</Operator>
                                <ValueExpression>
                                    <Value Type="String"> ServiceName$</Value>
                                </ValueExpression>
                            </SimpleExpression>
                        </Expression>
                    </And>
                </Expression>
            </DataSource>
        </DataSources>
        <WriteActions>
            <WriteAction  >
                <Priority>2</Priority>
                <Severity>2</Severity>
                <AlertName />
                <AlertDescription />
                <AlertOwner />
    
                <AlertParameters>
                    <AlertParameter1>$Data/EventDescription$</AlertParameter1>
                </AlertParameters>
                <Suppression>
                    <SuppressionValue />
                </Suppression>
    
            </WriteAction>
        </WriteActions>
    </Rule>
    

    MY CURRENT XSL:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">
    
        <xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="/*/Rule/DataSources/DataSource">
            <xsl:element name="{local-name()}">  
                <xsl:value-of select="."/>
            </xsl:element>
            <xsl:apply-templates select="node()"/>
        </xsl:template> 
    
        <xsl:template name="resolveexpr" match="/*/Rule/DataSources/DataSource">
            <xsl:choose>
                <xsl:when test="contains(name(.),'Expression')">
                    <xsl:text>sometext</xsl:text>   
                </xsl:when>     
                <xsl:otherwise />
            </xsl:choose>
        </xsl:template>
    </xsl:stylesheet>  
    

    希望输出: 如下所示。 但我的最终目标是将其带入excel表。

    <Rule>
      <ID>id823</ID>
      <Enabled>true</Enabled>
      <ConfirmDelivery>true</ConfirmDelivery>
      <Remotable>true</Remotable >
      <Category>EventCollection</Category>
      <DataSources>
        <DataSource>
          <TypeID>Windows!Microsoft.Windows.EventProvider>
          <ComputerName>NetworkName$</ComputerName>
          <LogName>Application</LogName>
          <Expression>
            <And>((((EventDisplayNumber))(Equal)((823))))((((PublisherName))(Equal)(( ServiceName$))))</And>
          </Expression>
        </DataSource>
      </DataSources>
      <WriteActions>
        <WriteAction  >
          <Priority>2</Priority>
          <Severity>2</Severity>
          <AlertParameters>
            <AlertParameter1>$Data/EventDescription$</AlertParameter1>
          </AlertParameters>
          <Suppression>
            <SuppressionValue />
          </Suppression>
        </WriteAction>
      </WriteActions>
    </Rule>
    

1 个答案:

答案 0 :(得分:0)

您已使用身份模板开始了正确的轨道,但从您的示例的外观来看,您希望将属性转换为元素。因此,您需要从身份模板匹配中删除@*模式,并创建另一个模板以匹配属性。

<xsl:template match="@*">
    <xsl:element name="{local-name()}">  
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

您需要的其他模板可能与构建表达式有关。你还没有真正解释这个的完整逻辑,但它看起来像是输出括号括起来的值的情况。像这样的东西

<xsl:template match="SimpleExpression">
    <xsl:text>(</xsl:text>
        <xsl:apply-templates />
   <xsl:text>)</xsl:text>
</xsl:template>

<xsl:template match="ValueExpression|Operator">
    <xsl:text>(</xsl:text>
        <xsl:value-of select="." />
    <xsl:text>)</xsl:text>
</xsl:template>

看起来您只想输出最顶层的 Expression 元素,因此您需要一个模板来跳过任何后代

<xsl:template match="Expression[ancestor::Expression]">
        <xsl:apply-templates />
</xsl:template>

等元素会被身份转换所淹没。

试试这个XSLT。这可能无法满足您的需求,但它应该为您提供更多开始指示您的方式:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="@*">
        <xsl:element name="{local-name()}">  
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="Expression[ancestor::Expression]">
            <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="SimpleExpression">
        <xsl:text>(</xsl:text>
            <xsl:apply-templates />
       <xsl:text>)</xsl:text>
    </xsl:template>

        <xsl:template match="ValueExpression|Operator">
        <xsl:text>(</xsl:text>
            <xsl:value-of select="." />
        <xsl:text>)</xsl:text>
    </xsl:template>
</xsl:stylesheet>