XSLT。根据另一个节点的存在抑制一个节点
XSLT. Suppressing a node based on existence of another node
我有一个源 xml 文件如下:
<PortfolioStatement xmlns="http://composition.bowne.com/2010/v4">
<section xmlns="" name="Schedule of Investments" code="" type="Table" fundid="19" subtype="SOI" style="">
<table xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" accountperiod="2014-10-31" style="SOI_Abbr" accountperiodtype="0" code="Abbreviation" name="Holdings" fundid="19" type="" cols="4">
<colspec colnum="1" colname="1"/>
<colspec colnum="2" colname="2"/>
<colspec colnum="3" colname="3"/>
<colspec colnum="4" colname="4"/>
<tbody>
<tr layoutcode="" type="detail" level="2" itemtype="detail"> (node 1)
<td colname="1">[~ABSYMB]ABC[#~ABSYMB]</td>
<td colname="2">American Depositary Receipt</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]LP[#~ABSYMB]</td>
<td colname="2">Limited Partnership</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]REIT[#~ABSYMB]</td>
<td colname="2">Real Estate Investment Trust</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail"> (node 2)
<td colname="1">[~ABSYMB]DEF[#~ABSYMB]</td>
<td colname="2">Sponsored American Depositary Receipt</td>
<td colname="3"/>
<td colname="4"/>
</tr>
</tbody>
</table>
</section>
</PortfolioStatement>
如果节点 2 存在,我想做的是抑制节点 1(如标记)。节点 1 被定义为在其子 td 节点的标签 [~ABSYMB] 和 [#~ABSYMB] 之间具有文本 'ABC'。节点 2 被定义为在其子 td 节点的标签 [~ABSYMB] 和 [#~ABSYMB] 之间具有文本 'DEF'。这将使结果 xml 看起来像这样:
<PortfolioStatement xmlns="http://composition.bowne.com/2010/v4">
<section xmlns="" name="Schedule of Investments" code="" type="Table" fundid="19" subtype="SOI" style="">
<table xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" accountperiod="2014-10-31" style="SOI_Abbr" accountperiodtype="0" code="Abbreviation" name="Holdings" fundid="19" type="" cols="4">
<colspec colnum="1" colname="1"/>
<colspec colnum="2" colname="2"/>
<colspec colnum="3" colname="3"/>
<colspec colnum="4" colname="4"/>
<tbody>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]LP[#~ABSYMB]</td>
<td colname="2">Limited Partnership</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]REIT[#~ABSYMB]</td>
<td colname="2">Real Estate Investment Trust</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]DEF[#~ABSYMB]</td>
<td colname="2">Sponsored American Depositary Receipt</td>
<td colname="3"/>
<td colname="4"/>
</tr>
</tbody>
</table>
</section>
</PortfolioStatement>
文本值 'ABC' 和 'DEF' 设置为参数。到目前为止,我的 xslt 看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:arcml="http://composition.bowne.com/2010/v4"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="fn msxml xsl arcml xsd xsi">
<xsl:output indent="yes" method="xml" version="1.0" omit-xml-declaration="no"/>
<!-- Parameters -->
<xsl:param name="Text1">ABC</xsl:param>
<xsl:param name="Text2">DEF</xsl:param>
<!-- Identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tr[td]">
<xsl:choose>
<xsl:when test="substring-before(substring-after(.,'[~ABSYMB]'),'[#~ABSYMB]')=$Text1">
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这找到了 node1,但我不知道如何检查 node2 是否存在以执行匹配模式覆盖。
我觉得描述我的问题可能比解决它更令人困惑,为此我深表歉意。非常感谢任何人的任何建议。
你可以用following
斧子试试这个方法:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="tr[td='[~ABSYMB]ABC[#~ABSYMB]' and following::td='[~ABSYMB]DEF[#~ABSYMB]']"/>
</xsl:stylesheet>
您需要禁止任何 tr
具有
- a
td
child 内容 concat('[~ABSYMB]',$Text1,'[#~ABSYMB]')
and
- 一个
tr
兄弟姐妹,它又具有 td
child 内容 concat('[~ABSYMB]',$Text2,'[#~ABSYMB]')
事情有点复杂,因为在 XSLT 1.0 中您不能在模板匹配模式中使用变量,所以您不能使用完全空模板的常用技术来匹配您想要抑制的内容.相反,您需要一个匹配 all tr
元素的模板,然后该模板中的逻辑来决定是否保留它们。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" version="1.0" omit-xml-declaration="no"/>
<!-- Parameters -->
<xsl:param name="Text1">ABC</xsl:param>
<xsl:param name="Text2">DEF</xsl:param>
<!-- Identity template, with a name so we can call it -->
<xsl:template match="node()|@*" name="ident">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tr">
<!-- if this tr is _not_ one we want to suppress... -->
<xsl:if test="
not(
td = concat('[~ABSYMB]',$Text1,'[#~ABSYMB]')
and
../tr[td = concat('[~ABSYMB]',$Text2,'[#~ABSYMB]')]
)">
<!-- ... then delegate to the identity template -->
<xsl:call-template name="ident" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
我有一个源 xml 文件如下:
<PortfolioStatement xmlns="http://composition.bowne.com/2010/v4">
<section xmlns="" name="Schedule of Investments" code="" type="Table" fundid="19" subtype="SOI" style="">
<table xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" accountperiod="2014-10-31" style="SOI_Abbr" accountperiodtype="0" code="Abbreviation" name="Holdings" fundid="19" type="" cols="4">
<colspec colnum="1" colname="1"/>
<colspec colnum="2" colname="2"/>
<colspec colnum="3" colname="3"/>
<colspec colnum="4" colname="4"/>
<tbody>
<tr layoutcode="" type="detail" level="2" itemtype="detail"> (node 1)
<td colname="1">[~ABSYMB]ABC[#~ABSYMB]</td>
<td colname="2">American Depositary Receipt</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]LP[#~ABSYMB]</td>
<td colname="2">Limited Partnership</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]REIT[#~ABSYMB]</td>
<td colname="2">Real Estate Investment Trust</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail"> (node 2)
<td colname="1">[~ABSYMB]DEF[#~ABSYMB]</td>
<td colname="2">Sponsored American Depositary Receipt</td>
<td colname="3"/>
<td colname="4"/>
</tr>
</tbody>
</table>
</section>
</PortfolioStatement>
如果节点 2 存在,我想做的是抑制节点 1(如标记)。节点 1 被定义为在其子 td 节点的标签 [~ABSYMB] 和 [#~ABSYMB] 之间具有文本 'ABC'。节点 2 被定义为在其子 td 节点的标签 [~ABSYMB] 和 [#~ABSYMB] 之间具有文本 'DEF'。这将使结果 xml 看起来像这样:
<PortfolioStatement xmlns="http://composition.bowne.com/2010/v4">
<section xmlns="" name="Schedule of Investments" code="" type="Table" fundid="19" subtype="SOI" style="">
<table xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" accountperiod="2014-10-31" style="SOI_Abbr" accountperiodtype="0" code="Abbreviation" name="Holdings" fundid="19" type="" cols="4">
<colspec colnum="1" colname="1"/>
<colspec colnum="2" colname="2"/>
<colspec colnum="3" colname="3"/>
<colspec colnum="4" colname="4"/>
<tbody>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]LP[#~ABSYMB]</td>
<td colname="2">Limited Partnership</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]REIT[#~ABSYMB]</td>
<td colname="2">Real Estate Investment Trust</td>
<td colname="3"/>
<td colname="4"/>
</tr>
<tr layoutcode="" type="detail" level="2" itemtype="detail">
<td colname="1">[~ABSYMB]DEF[#~ABSYMB]</td>
<td colname="2">Sponsored American Depositary Receipt</td>
<td colname="3"/>
<td colname="4"/>
</tr>
</tbody>
</table>
</section>
</PortfolioStatement>
文本值 'ABC' 和 'DEF' 设置为参数。到目前为止,我的 xslt 看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:arcml="http://composition.bowne.com/2010/v4"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="fn msxml xsl arcml xsd xsi">
<xsl:output indent="yes" method="xml" version="1.0" omit-xml-declaration="no"/>
<!-- Parameters -->
<xsl:param name="Text1">ABC</xsl:param>
<xsl:param name="Text2">DEF</xsl:param>
<!-- Identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tr[td]">
<xsl:choose>
<xsl:when test="substring-before(substring-after(.,'[~ABSYMB]'),'[#~ABSYMB]')=$Text1">
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这找到了 node1,但我不知道如何检查 node2 是否存在以执行匹配模式覆盖。
我觉得描述我的问题可能比解决它更令人困惑,为此我深表歉意。非常感谢任何人的任何建议。
你可以用following
斧子试试这个方法:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="tr[td='[~ABSYMB]ABC[#~ABSYMB]' and following::td='[~ABSYMB]DEF[#~ABSYMB]']"/>
</xsl:stylesheet>
您需要禁止任何 tr
具有
- a
td
child 内容concat('[~ABSYMB]',$Text1,'[#~ABSYMB]')
and - 一个
tr
兄弟姐妹,它又具有td
child 内容concat('[~ABSYMB]',$Text2,'[#~ABSYMB]')
事情有点复杂,因为在 XSLT 1.0 中您不能在模板匹配模式中使用变量,所以您不能使用完全空模板的常用技术来匹配您想要抑制的内容.相反,您需要一个匹配 all tr
元素的模板,然后该模板中的逻辑来决定是否保留它们。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" version="1.0" omit-xml-declaration="no"/>
<!-- Parameters -->
<xsl:param name="Text1">ABC</xsl:param>
<xsl:param name="Text2">DEF</xsl:param>
<!-- Identity template, with a name so we can call it -->
<xsl:template match="node()|@*" name="ident">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tr">
<!-- if this tr is _not_ one we want to suppress... -->
<xsl:if test="
not(
td = concat('[~ABSYMB]',$Text1,'[#~ABSYMB]')
and
../tr[td = concat('[~ABSYMB]',$Text2,'[#~ABSYMB]')]
)">
<!-- ... then delegate to the identity template -->
<xsl:call-template name="ident" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>