如果属性值高于阈值,则 XSLT 删除数据
XSLT remove data if attribute value is higher than threshold
我是 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
有关系吗?
第一件事:你应该在你的输入XML中使用 namespace/s,而不是用像*[contains(local-name(),'...')]
这样尴尬的表达方式围着他们转。
现在,排除特定节点的最简单方法是从 identity transform 模板(如您所用)开始复制所有节点作为规则,然后添加一个空模板匹配要作为例外排除的节点。
但是,当您要排除的节点由参数确定时,这将不起作用,因为模板的匹配模式不能包含对变量的引用。在这种情况下,您可以使模板的 content 成为条件:
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 < $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)转义<
运算符为 <
.
另一种解决方案将确保模板仅应用于满足条件的 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 < $maxEventNum]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
假设-基于预期输出XML-您想要在family
及其后代元素f.eperformanceIndicator
元素中评估eventNumber
属性, 您可以尝试以下 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(.) >= $maxEventNum]) = 0">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
- 第一个模板是标识模板,它匹配所有节点和属性并将它们复制到输出 XML,因为它在源 XML.
中
- 第二个模板覆盖了匹配元素的身份模板 -
family
元素在这种情况下 -;更具体的模板会覆盖更通用的模板。此模板测试 eventNumber
属性 在 当前上下文 family
中的值是否 等于或高于 阈值(您 隐含地声明当阈值本身为020004
时,eventNumber=020004
应该从输出中移除。如果有 none 这样的 eventNumber
属性 (count(...)=0
),复制当前 family
元素到输出,否则不要 copy/do nothing.
我是 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
有关系吗?
第一件事:你应该在你的输入XML中使用 namespace/s,而不是用像*[contains(local-name(),'...')]
这样尴尬的表达方式围着他们转。
现在,排除特定节点的最简单方法是从 identity transform 模板(如您所用)开始复制所有节点作为规则,然后添加一个空模板匹配要作为例外排除的节点。
但是,当您要排除的节点由参数确定时,这将不起作用,因为模板的匹配模式不能包含对变量的引用。在这种情况下,您可以使模板的 content 成为条件:
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 < $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)转义<
运算符为 <
.
另一种解决方案将确保模板仅应用于满足条件的 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 < $maxEventNum]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
假设-基于预期输出XML-您想要在family
及其后代元素f.eperformanceIndicator
元素中评估eventNumber
属性, 您可以尝试以下 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(.) >= $maxEventNum]) = 0">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
- 第一个模板是标识模板,它匹配所有节点和属性并将它们复制到输出 XML,因为它在源 XML. 中
- 第二个模板覆盖了匹配元素的身份模板 -
family
元素在这种情况下 -;更具体的模板会覆盖更通用的模板。此模板测试eventNumber
属性 在 当前上下文family
中的值是否 等于或高于 阈值(您 隐含地声明当阈值本身为020004
时,eventNumber=020004
应该从输出中移除。如果有 none 这样的eventNumber
属性 (count(...)=0
),复制当前family
元素到输出,否则不要 copy/do nothing.