2017-05-16 16 views
1

子ノードに基づいて親ノードを削除する方法について質問があります。 XMLファイルの構造は次の通りですXSL:子ノードが重複している親ノードを削除

<PlmXmlData xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:plm="http://www.plmxml.org/Schemas/PLMXMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:an=""> 
    <ItemList> 
    <Item> 
     <ID>1</ID> 
     <Group>Group1</Group> 
     <Projekt>Projekt1</Projekt> 
     <DatasetList> 
     <Dataset> 
      <Name>Name1</Name> 
      <Type>TXT</Type> 
      <Template>None</Template> 
      <RelativeFilePath>FilePath1</RelativeFilePath> 
      <PropertyList> 
      <Property> 
       <Title>item_name</Title> 
       <Value>ITEM_Name</Value> 
      </Property> 
      <Property> 
       <Title>item_name</Title> 
       <Value>ITEM_Name</Value> 
      </Property> 
      </PropertyList> 
     </Dataset> 
     <Dataset> 
      <Name>Name1</Name> 
      <Type>PDF</Type> 
      <Template>Template1</Template> 
      <RelativeFilePath>FilePath1/Name1.pdf</RelativeFilePath> 
      <PropertyList> 
      <Property> 
       <Title>item_name</Title> 
       <Value>CAR1</Value> 
      </Property> 
      <Property> 
       <Title>item_name</Title> 
       <Value>CAR1</Value> 
      </Property> 
      <Property> 
       <Title>item_name2</Title> 
       <Value>CAR2</Value> 
      </Property> 
      <Property> 
       <Title>item_name2</Title> 
       <Value>CAR2</Value> 
      </Property> 
      </PropertyList> 
     </Dataset> 
     </DatasetList> 
    </Item> 
    </ItemList> 
</PlmXmlData> 

あなたはこの例ではTXTやPDFで異なる<Type>ノードがある見ることができるように。 このノードには、ノード<Property>と子ノード<Title><Value>があります。

ノード<Title><Value>をそれぞれ<Type>の重複したエントリごとに削除したいとします。

所望の出力は次のようにする必要があります:私は、フォーラムを検索するが、フィッティング解決策を見つけるcould'ntいる

<PlmXmlData xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:plm="http://www.plmxml.org/Schemas/PLMXMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:an=""> 
    <ItemList> 
    <Item> 
     <ID>1</ID> 
     <Group>Group1</Group> 
     <Projekt>Projekt1</Projekt> 
     <DatasetList> 
     <Dataset> 
      <Name>Name1</Name> 
      <Type>TXT</Type> 
      <Template>None</Template> 
      <RelativeFilePath>FilePath1</RelativeFilePath> 
      <PropertyList> 
      <Property> 
       <Title>item_name</Title> 
       <Value>ITEM_Name</Value> 
      </Property> 
      </PropertyList> 
     </Dataset> 
     <Dataset> 
      <Name>Name1</Name> 
      <Type>PDF</Type> 
      <Template>Template1</Template> 
      <RelativeFilePath>FilePath1/Name1.pdf</RelativeFilePath> 
      <PropertyList> 
      <Property> 
       <Title>item_name</Title> 
       <Value>CAR1</Value> 
      </Property> 
      <Property> 
       <Title>item_name2</Title> 
       <Value>CAR2</Value> 
      </Property> 
      </PropertyList> 
     </Dataset> 
     </DatasetList> 
    </Item> 
    </ItemList> 

。ご協力いただきありがとうございます。

+0

XSLT 1.0またはXSLT 2.0のいずれかを選択してください。両方を選択してください。重複を削除するには、* grouping *を検索します。おそらく、ここで最も頻繁に尋ねられるXSLTの質問です。 –

答えて

1

ここにXSLT 1.0のソリューションがあります。

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

    <xsl:output method="xml" indent="yes"/> 

    <xsl:key name="property" match="Property" use="concat(generate-id(parent::*), Title, '|', Value)" /> 

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

    <xsl:template match="PropertyList"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*" /> 
      <xsl:apply-templates select="Property[generate-id(.) = generate-id(key('property', concat(generate-id(parent::*), Title, '|', Value))[1])]" /> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

それは特定の条件のために、XMLを超えるマッチを見つけるためにkey関数を使用して「Muenchianグルーピング」と呼ばれる技術を使用して、現在のコンテキストに、その最初の試合と同じであるか否かをチェック重複を無視する。等価チェックはgenerate-id関数を使用します。各XML要素には、実行時に明示的または暗黙的に生成されたid属性があり、一意に識別します。

この場合、キーは<Property>要素に一致し、それらにインデックスを付けます。 <PropertyList>内の重複を削除し、XML全体で重複を削除しないようにするために、キーには、親の<PropertyList>、(012)要素の値の<Title>|シンボル、および<Value>要素値の連結。つまり、この部分が何をするかです:

<xsl:key name="property" match="Property" use="concat(generate-id(parent::*), Title, '|', Value)" /> 

再帰的にテンプレートを適用されますが、これだけ述語が成り立つ<Property>要素について、次に<PropertyList>に一致するテンプレート:[generate-id(.) = generate-id(key('property', concat(generate-id(parent::*), Title, '|', Value))[1])]

それを打破するのをしてみましょう。 generate-id(.)は、現在のノード(Property要素)のidを生成します。次に、そのIDが生成されたidと同じかどうかを確認します。key('property', concat(generate-id(parent::*), Title, '|', Value))[1]

「生成された親(PropertyList)のID、タイトル、|の生成されたIDおよび値」を取得し、一致したノードセットの最初の要素のみを取得します。あなたはこのように述べ

注:

あなたはこの例ではTXTやPDF内の別のノードがある見ることができるように。このノード内にはノードと子ノードがあります。

私はそれぞれのタイプ(TXT、PDF、...)は、指定された<DatasetList>に1回だけ出現し、PropertyListにローカルの複製を削除したいと考えています。タイプが繰り返され、タイプ全体で重複を削除したい場合は、Muenchianグループを別のレベル(タイプを含む)にする必要があります。しかし、私は上記の解決策があなたが目指していたものだと考えています。

また、タイトルと値の要素に|のシンボルが含まれている可能性があります。その場合、別のセパレータを選択することができます。

XSLT 2を使用できる場合は、グループ化が組み込まれているため、これはずっと簡単になります。その場合は、あなたの質問で指定してください。新しい回答ができます。

+0

説明をいただきありがとうございます!私はあなたの方法を試して、タグ ''と ''を削除することを除いてこれまでのところ動作します。これらの要素をファイルに保存するにはどうすればよいですか? 編集:タグを追加しました。ありがとうございました! – M4rk0444

+0

@ M4rk0444おっと、そうです。テンプレートはPropertyListと一致しますが、現在のノードをコピーせずにProperty要素を処理するようにまっすぐに進みます。今すぐXSLTを編集して修正します。 –

+0

ありがとう!これは私をたくさん助けました! – M4rk0444

関連する問題