根据子节点过滤XML

时间:2011-10-06 23:20:39

标签: xml xslt

我有一个类似于此的XML文件(删除了更多节点和详细信息):

<?xml version="1.0" encoding="utf-8"?>
<Message xmlns="http://www.theia.org.uk/ILR/2011-12/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
    <CollectionDetails>
        <Collection>ILR</Collection>
        <Year>1112</Year>
        <FilePreparationDate>2011-10-06</FilePreparationDate>
    </CollectionDetails>
    <Source>
        <ProtectiveMarking>PROTECT-PRIVATE</ProtectiveMarking>          
    </Source>
</Header>
<SourceFiles>
    <SourceFile>
        <SourceFileName>A10004705001112004401.ER</SourceFileName>
        <FilePreparationDate>2011-10-05</FilePreparationDate>
    </SourceFile>
</SourceFiles>
<LearningProvider>
    <UKPRN>10004705</UKPRN>
    <UPIN>107949</UPIN>
</LearningProvider>
<Learner>
    <ULN>4682272097</ULN>
    <GivenNames>Peter</GivenNames>
    <LearningDelivery>
        <LearnAimRef>60000776</LearnAimRef>         
    </LearningDelivery>     
    <LearningDelivery>
        <LearnAimRef>ZPROG001</LearnAimRef>         
    </LearningDelivery>
</Learner>
<Learner>
    <ULN>3072094321</ULN>       
    <GivenNames>Thomas</GivenNames>     
    <LearningDelivery>
        <LearnAimRef>10055320</LearnAimRef>         
    </LearningDelivery>
    <LearningDelivery>
        <LearnAimRef>10002856</LearnAimRef>         
    </LearningDelivery>
    <LearningDelivery>
        <LearnAimRef>1000287X</LearnAimRef>         
    </LearningDelivery>
</Learner>
</Message>

我需要对此进行过滤,以便只有具有ZPROG001的子LearningDelivery LearnAimRef的学习者记录才会显示,因此这种情况下的输出将是第一个学习者而不是第二个:

<?xml version="1.0" encoding="utf-8"?>
<Message xmlns="http://www.theia.org.uk/ILR/2011-12/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
    <CollectionDetails>
        <Collection>ILR</Collection>
        <Year>1112</Year>
        <FilePreparationDate>2011-10-06</FilePreparationDate>
    </CollectionDetails>
    <Source>
        <ProtectiveMarking>PROTECT-PRIVATE</ProtectiveMarking>          
    </Source>
</Header>
<SourceFiles>
    <SourceFile>
        <SourceFileName>A10004705001112004401.ER</SourceFileName>
        <FilePreparationDate>2011-10-05</FilePreparationDate>
    </SourceFile>
</SourceFiles>
<LearningProvider>
    <UKPRN>10004705</UKPRN>
    <UPIN>107949</UPIN>
</LearningProvider>
<Learner>
    <ULN>4682272097</ULN>
    <GivenNames>Peter</GivenNames>
    <LearningDelivery>
        <LearnAimRef>60000776</LearnAimRef>         
    </LearningDelivery>     
    <LearningDelivery>
        <LearnAimRef>ZPROG001</LearnAimRef>         
    </LearningDelivery>
</Learner>
</Message>

我已经研究过如何做到这一点并且相信正确的方法是使用XSL转换来处理xml并根据需要输出到新文件(在c#中执行此操作)。几个小时后,我试图围绕XSLT语法包围我仍然卡住,无法得到我想要的输出。任何帮助非常感谢。

2 个答案:

答案 0 :(得分:5)

要复制大多数XML源文档,仅修改某些部分,您需要从身份转换开始。这只是复制一切。然后添加模板以覆盖您不想复制的<Learner>元素的标识模板:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:theia="http://www.theia.org.uk/ILR/2011-12/1">
  <!-- identity template -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <!-- override the above template for certain Learner elements; output nothing. -->
  <xsl:template match="theia:Learner[
     not(theia:LearningDelivery/theia:LearnAimRef = 'ZPROG001')]">
  </xsl:template>
</xsl:stylesheet>

(从@andyb借用名称空间前缀)。

答案 1 :(得分:1)

如果您只想要具有特定值的所有具有后代的<Learner>元素(在本例中为 LearnAimRef ),则可以使用谓词表达式({{之间的位) 1}}和[)来过滤节点集。

]

所以<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:theia="http://www.theia.org.uk/ILR/2011-12/1"> <xsl:template match="/theia:Message"> <xsl:copy-of select="theia:Learner[theia:LearningDelivery/theia:LearnAimRef='ZPROG001']"/> </xsl:template> </xsl:stylesheet> 读取为复制所有学习者节点,其中有一个名为LearningDelivery的子节点,其中有一个名为LearnAimRef的子节点,其值等于ZPROG001

你的XML文档有一个default namespacehttp://www.theia.org.uk/ILR/2011-12/1”所以为了让XPath正确选择一个节点,它必须使用相同的命名空间声明,所以在上面的XSLT中,我有将您的命名空间分配给别名并在XPath中使用它。

如果您希望XML源的其他部分复制到输出树,则可以添加其他规则,例如copy-of

这不是在C#中应用转换的答案,但已经回答过了 - How to apply an XSLT Stylesheet in C#

希望这会有所帮助:)