2011-10-06 170 views
4

我有類似這樣的XML文件(除去更多的節點和細節):過濾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> 

我需要過濾此,使得有孩子的LearningDelivery LearnAimRef只有學習者記錄ZPROG001將顯示所以在這種情況下,輸出將是第一個學生,但不是第二:

<?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語法包裝我的頭,我仍然卡住,無法獲得我想要的輸出。任何幫助非常感謝。

回答

4

要複製大多數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爲一個很好的答案。 –

+0

優秀的答案,這正是我想要的。我希望我能更多地理解XSLT,但它對我來說只是一次。 – PeteT

1

如果你只是希望所有具有後代(在這種情況下LearnAimRef)的<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"> 
<xsl:template match="/theia:Message"> 
    <xsl:copy-of select="theia:Learner[theia:LearningDelivery/theia:LearnAimRef='ZPROG001']"/> 
</xsl:template> 
</xsl:stylesheet> 

所以copy-of全文複製所有學習者的節點,有一個叫LearningDelivery孩子其中有一個叫LearnAimRef的孩子,有等於ZPROG001

你的XML文檔中的值具有default namespace的「http://www.theia.org.uk/ILR/2011-12/1」,所以爲了讓XPath正確選擇一個節點,它必須使用相同的名稱空間聲明,因此在上面的XSLT中,我已將您的名稱空間分配給別名,並在XPath中使用它。

如果你想在XML源複製到輸出樹的其他部分,你可以添加更多的規則,例如<xsl:copy-of select="theia:LearningProvider"/>

這不是在C#應用轉換的答案,但是這已經被回答 - How to apply an XSLT Stylesheet in C#

希望這有助於:)

+0

在展示如何選擇所需的學習者元素方面做得很好,特別是在命名空間問題上。然而,OP在他期望的輸出中顯示他希望複製大部分文檔;只有''沒有正確內容的元素將被忽略。 – LarsH

+0

是的,我提到了在答案中複製更多節點並且XSLT不完整。 +1爲你更清潔和更完整的答案。 – andyb

+0

感謝您的回答,我已經制定了C#方面的事情,這是我遇到的實際XSLT文件。 – PeteT