如果属性值高于阈值

时间:2015-06-13 12:25:59

标签: xml xslt math operator-keyword relational

我是XSLT的新手。我的目的是基于字段从XML中删除元素,如果它高于某个阈值,我将作为参数获取它。

我的XML如下所示:

<tns:PM objectClass="MyNode" objectName="" className="com.project.converter.PMFamilyConverter" interfaceName="ComponentPM"
    xmlns:tns="http://www.myproject/SS/PMSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.myProject.com/SS/PM.xsd">
  <tns:family desc="family0" id="f0" eventNumber="000000">
    <tns:performanceIndicator desc="Description 1" id="Success" eventNumber="000001" />
    <tns:performanceIndicator desc="Description 2" id="Error" eventNumber="000002" />
  </tns:family>
  <tns:family desc="family1" id="f1" eventNumber="010000">
    <tns:performanceIndicator desc="Description 1" id="Success" eventNumber="010001" />
    <tns:performanceIndicator desc="Description 2" id="Name Error" eventNumber="010002" />
    <tns:performanceIndicator desc="Description 3" id="Server Not Found Error" eventNumber="010003" />
  </tns:family>
  <tns:family desc="family2" id="f2" eventNumber="020000">
    <tns:performanceIndicator desc="Description 1" id="Success" eventNumber="020001" />
    <tns:performanceIndicator desc="Description 2" id="Format Error" eventNumber="020002" />
    <tns:performanceIndicator desc="Description 3" id="Logic Error" eventNumber="020003" />
    <tns:performanceIndicator desc="Description 4" id="Success with warning message" eventNumber="020004" />
  </tns:family>
  <tns:family desc="family3" id="f3" eventNumber="030000">
    <tns:performanceIndicator desc="Description 1" id="Success" eventNumber="030001" />
    <tns:performanceIndicator desc="Description 2" id="Error" eventNumber="030002" />
  </tns:family>
</tns:PM>

根据网上提供的一些样本,我写的XSL是:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="no" indent="yes"/>
<xsl:param name="maxEventNum"/>
<xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>
    <xsl:template match="/">
      <xsl:apply-templates select="/*[contains(local-name(),'PM')]/*[contains(local-name(),'family')]/@eventNumber"/>
      <xsl:if test="number(.) < $maxEventNum">
            <xsl:copy-of select="/*[contains(local-name(),'PM')]/*[contains(local-name(),'family')]"/>
      </xsl:if>
    </xsl:template>
</xsl:stylesheet>

如果我将maxEventNumber作为020004传递,我想要的输出如下所示。

<tns:PM objectClass="MyNode" objectName="" className="com.project.converter.PMFamilyConverter" interfaceName="ComponentPM"
    xmlns:tns="http://www.myproject/SS/PMSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.myProject.com/SS/PM.xsd">
  <tns:family desc="family0" id="f0" eventNumber="000000">
    <tns:performanceIndicator desc="Description 1" id="Success" eventNumber="000001" />
    <tns:performanceIndicator desc="Description 2" id="Error" eventNumber="000002" />
  </tns:family>
  <tns:family desc="family1" id="f1" eventNumber="010000">
    <tns:performanceIndicator desc="Description 1" id="Success" eventNumber="010001" />
    <tns:performanceIndicator desc="Description 2" id="Name Error" eventNumber="010002" />
    <tns:performanceIndicator desc="Description 3" id="Server Not Found Error" eventNumber="010003" />
  </tns:family>
</tns:PM>

您也可以告诉apply-template何时以及如何使用match如果在apply-template内使用match则与@Override public void onAttach(Activity activity) { super.onAttach(activity); if (activity instanceof CustomListener) { listener = (CustomListener)activity; } else { throw new ClassCastException("Parent activity must implement CustomListener"); } } 相关。

2 个答案:

答案 0 :(得分:1)

第一件事:您应该在您的输入XML中使用命名空间/ s,而不是使用像*[contains(local-name(),'...')]这样的尴尬表达式来围绕它们跳舞。

现在,排除特定节点的最简单方法是从身份转换模板开始(如您所示)将所有节点复制为规则,然后添加与您想要的节点匹配的空模板排除作为例外。

但是,当您要排除的节点由参数确定时,这不起作用,因为模板的匹配模式不能包含对变量的引用。在这种情况下,您可以使模板的内容成为条件:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tns="http://www.myproject/SS/PMSchema">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="maxEventNum" select="020004"/>

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

<xsl:template match="tns:family">
    <xsl:if test="@eventNumber &lt; $maxEventNum">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

注意 :( 1)添加的xmlns:tns="http://www.myproject/SS/PMSchema"命名空间声明和tns:前缀的使用,以及(2)<运算符的转义为&lt;

另一种解决方案是确保模板仅应用于符合条件的tns:family个节点:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tns="http://www.myproject/SS/PMSchema">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="maxEventNum" select="020004"/>

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

<xsl:template match="/tns:PM">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="tns:family[@eventNumber &lt; $maxEventNum]"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

假设 - 基于预期的输出XML-您想要评估eventNumber及其后代元素fe family元素中的performanceIndicator属性,您可以尝试以下XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tns="http://www.myproject/SS/PMSchema">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="no" indent="yes"/>
<xsl:strip-space elements="*"/>
  <xsl:param name="maxEventNum" select="020004"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/tns:PM/tns:family">
    <xsl:if test="count(.//@eventNumber[number(.) &gt;= $maxEventNum]) = 0">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
      </xsl:copy>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>
  • 第一个模板是标识模板,它匹配所有节点和属性,并将它们复制到源XML中的输出XML。
  • 第二个模板会覆盖匹配元素的标识模板 - 在这种情况下为family个元素 - ;更具体的模板会覆盖更一般的模板。此模板测试当前上下文eventNumber中的任何family属性是否值等于或高于而非隐式表示当自身的阈值为eventNumber=020004时,应从输出中删除020004。如果没有此类eventNumber属性(count(...)=0),请将当前family元素复制到输出中,否则不要复制/不执行任何操作。