如何在条件为真时复制除一个节点之外的所有节点

How to copy all the nodes except one when a condition is true

我得到了以下 XML.

     <?xml version="1.0" encoding="utf-8"?>
     <Students>
      <Student>
       <StdId value="1"/>
       <Name>a</Name>
       <Courses>
         <Course Id="2" value="c1"/>
        <Course Id="3" value="c2"/>
        <Course Id="4" value="c3"/>
       </Courses>
       <Addresses>
         <Address Id="2" type="permanent">
            <address1>my address</address1>
        </Address>
        <Address Id="4" type="Temporary">
            <address1>my address temp address</address1>
        </Address>
       </Addresses>
      </Student>
      <Student>
       <StdId value="2" InActive="True"/>
       <Name>b</Name>
       <Courses>
         <Course Id="2" value="c1"/>
        <Course Id="3" value="c4"/>
        <Course Id="5" value="c6"/>
       </Courses>
       <Addresses>
        <Address Id="2" type="permanent">
            <address1>my address</address1>
        </Address>
       </Addresses>
      </Student>
     </Students>

我的 xslt 是

     <?xml version="1.0" encoding="utf-8"?>
     <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
     <xsl:output method="xml" indent="yes"/>
     <xsl:strip-space elements="*" />
     <xsl:variable name="list" >1 4 6 15</xsl:variable> 
     <xsl:template match="/">       
    <xsl:result-document method="xml" href="file:///C:/Student_details.xml">
        <xsl:for-each select="Students/Student">                
            <xsl:variable name="vv1" select="Addresses/Address/@id" /> 
            <xsl:variable name="vv2" select="Courses/Course/@id" /> 
            <xsl:choose>
                <xsl:when test="contains($list, $vv1)">
                    <xsl:copy-of select=". except(Addresses)" />
                </xsl:when>
                <xsl:when test="contains($list, $vv2)">
                    <xsl:copy-of select=". except(Courses)" /> 
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="." />
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:result-document>
</xsl:template>

我想根据条件过滤一些节点。当地址@id 值在列表中时,复制除地址及其子项之外的所有内容。当 Course @id 值在列表中时,复制除课程及其子节点之外的所有内容。当上述条件 none 为真时,复制所有内容。我的 XSLT 代码复制了所有内容。

请注意,您的输入示例具有 Id 属性,而不是 id 属性,因此在 select 的 XPath 中,您需要 @Id 输入。我不确定我是否理解你的要求,假设你真的想删除任何 Courses 如果在列表中分别找到任何 Addresses,你可以简单地使用

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

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:variable name="list" >1 4 6 15</xsl:variable>
    <xsl:variable name="ids" select="tokenize($list, '\s+')"/>

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

    <xsl:template match="Student/Courses[Course/@Id = $ids] | Student/Addresses[Address/@Id = $ids]"/>
</xsl:transform>

对于您提供的创建结果的输入样本

<?xml version="1.0" encoding="UTF-8"?>
<Students>
   <Student>
      <StdId value="1"/>
      <Name>a</Name>
   </Student>
   <Student>
      <StdId value="2" InActive="True"/>
      <Name>b</Name>
      <Courses>
         <Course Id="2" value="c1"/>
         <Course Id="3" value="c4"/>
         <Course Id="5" value="c6"/>
      </Courses>
      <Addresses>
         <Address Id="2" type="permanent">
            <address1>my address</address1>
         </Address>
      </Addresses>
   </Student>
</Students>

如果您想明确创建结果文档,请使用例如

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:variable name="list" >1 4 6 15</xsl:variable>
    <xsl:variable name="ids" select="tokenize($list, '\s+')"/>

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

    <xsl:template match="/">
        <xsl:result-document>
            <xsl:apply-templates/>
        </xsl:result-document>
    </xsl:template>
    <xsl:template match="Student/Courses[Course/@Id = $ids] | Student/Addresses[Address/@Id = $ids]"/>
</xsl:transform>

请注意,您的原始代码中有 <xsl:variable name="list" >1 4 6 15</xsl:variable>,这并不是一个真正的列表,分别是一个值序列,因此我使用 <xsl:variable name="ids" select="tokenize($list, '\s+')"/> 以编程方式创建一个序列。然而,也可以简单地将变量值定义为执行 <xsl:variable name="ids" select="1, 4, 6, 15"/> 的整数序列,这样您就不需要标记化调用。