XSLT 通过仅过滤标记值等于的那些节点来创建另一个 XML

Posted

技术标签:

【中文标题】XSLT 通过仅过滤标记值等于的那些节点来创建另一个 XML【英文标题】:XSLT to create another XML by filtering only those node where tag value equals 【发布时间】:2021-08-07 12:32:24 【问题描述】:

我想在下面的文档示例中借助 XSLT 创建另一个 XML。这个想法是让所有学生的个人资料>城市是[PNH],无论他们的起源>地址>城市是什么。我知道在 XSLT 的帮助下,我们可以过滤掉并只复制我们希望在新 XML 文档中包含的内容。

<?xml version="1.0" encoding="utf-8"?>
<Class>    
    <Student>
        <Profile>
            <Name>G1</Name>
            <City>PNH</City>            
            <RegDate>2020-06-20</RegDate>
        </Profile>
        <Origin>
            <Address>
                <City>REP</City>
            </Address> 
        </Origin>
    </Student>
    <Student>
        <Profile>
            <Name>G4</Name>
            <City>REP</City>            
            <RegDate>2020-06-20</RegDate>
        </Profile>
        <Origin>
            <Address>
                <City>PNH</City>
            </Address> 
        </Origin>
    </Student>    
    <Student>
        <Profile>
            <Name>G3</Name>
            <City>PNH</City>            
            <RegDate>2020-06-20</RegDate>
        </Profile>
        <Origin>
            <Address>
                <City>PNH</City>
            </Address> 
        </Origin>
    </Student>
    <Student>
        <Profile>
            <Name>G5</Name>
            <City>KOS</City>            
            <RegDate>2020-06-20</RegDate>
        </Profile>
        <Origin>
            <Address>
                <City>PNH</City>
            </Address> 
        </Origin>
    </Student>
</Class>

我只想录取那些 Profile -> City 等于 'PNH' 的学生,这应该是最终的 XML 结果

<?xml version="1.0" encoding="utf-8"?>
<Class>    
    <Student>
        <Profile>
            <Name>G1</Name>
            <City>PNH</City>            
            <RegisterDate>2020-06-20</RegisterDate>
        </Profile>
        <Origin>
            <Address>
                <City>REP</City>
            </Address> 
        </Origin>
    </Student>   
    <Student>
        <Profile>
            <Name>G3</Name>
            <City>PNH</City>            
            <RegisterDate>2020-06-20</RegisterDate>
        </Profile>
        <Origin>
            <Address>
                <City>PNH</City>
            </Address> 
        </Origin>
    </Student>
</Class>

我已经尝试过了,但它仍然可以获取所有学生,但删除了城市不是 PNH 的 Profile Tag 中的数据

<xsl:template match="@*|node()">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="Profile[not(City = 'PNH')]"/>

【问题讨论】:

【参考方案1】:

如果你想排除满足某个条件的Students,那么你的模板必须匹配Student元素:

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

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

<xsl:template match="Student[not(Profile/City = 'PNH')]"/>

</xsl:stylesheet>

或者,您可以这样做:

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

<xsl:template match="/Class">
    <xsl:copy>
        <xsl:copy-of select="Student[Profile/City = 'PNH']"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

【讨论】:

太好了,它现在可以工作了。将属性 xsi:nil="true" 添加到标签时还有一个问题。初始加载文档时,C# 会在新 XPathDocument(sXmlPath) 上引发“xsi”未定义前缀的错误捕获。我想我应该再写一篇文章。 我也这么认为。

以上是关于XSLT 通过仅过滤标记值等于的那些节点来创建另一个 XML的主要内容,如果未能解决你的问题,请参考以下文章

XSLT如何仅对XML文档的字符串节点中的数值进行排序

从另一个节点 xslt 调用值

XSLT 过滤掉节点并生成新的 xml

xslt 通过子节点和位置选择 rss 项目

XSLT 导出过滤器产生不必要的空 XML 标记

如何通过重复值“另一列的大小”次来创建数组列?