2017-05-16 9 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>에있는 각 중복 항목에 대해 전체 노드 <Property>을 제거하고 싶습니다.

원하는 출력은 다음과 같이해야한다 : 나는이 포럼을 검색하지만, 피팅 해결책을 찾기 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 속성을 고유하게 식별하는 id 속성을 갖습니다.

이 경우 키는 <Property> 개의 요소와 일치하고 색인을 생성합니다. <PropertyList> 내에서 복제본을 제거하고 전체 XML에서 복제본을 제거하지 않으려는 경우 키는 부모 (<PropertyList>), <Title> (요소 값), | 심볼 및 <Value> 요소 값의 (생성 된) if의 연결을 "인덱스" . 하지만이 술어가 보유하고 <Property> 요소,

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

재귀 다음 <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]

"부모의 생성 된 ID (Google의 PropertyList), Title, |의 연결에 일치하는 키 이름 속성이 표시됩니다. 및 값 "을 검색 한 다음 일치하는 노드 집합의 첫 번째 요소 만 가져옵니다. 당신이이 말을

참고 :

이 예를 들어, TXT 및 PDF에서 다른 노드가 볼 수 있듯이. 이 노드에는 노드와 하위 노드가 있습니다.

각 유형 (TXT, PDF, ...)은 주어진 <DatasetList>에서 한 번만 발생하며 중복 된 로컬은 PropertyList에서 제거하려고합니다. 유형을 반복 할 수 있고 전체 유형에서 중복을 제거하려면 Muenchian 그룹을 다른 레벨 (유형 포함)으로 가져 가야합니다. 그러나 위의 해결책이 당신이 목표로 한 것이라고 생각합니다.

또한 제목 및 값 요소에 | 개의 기호가 포함될 수있는 경우이 오류가 발생할 수 있습니다. 이 경우 다른 구분 기호를 선택할 수 있습니다.

XSLT 2를 사용할 수있는 경우 그룹화 기능이 내장되어 있으므로 훨씬 간단 해집니다.이 경우 질문에 답안을 작성하면 새로운 답변을 얻을 수 있습니다.

+0

설명해 주셔서 감사합니다. 난 당신의 방법을 시도하고 태그''및''를 제거한다는 것을 제외하고는 지금까지 작동합니다. 어떻게 그 요소들을 파일에 보관할 수 있습니까? 편집 : 태그가 추가되었습니다! 고맙습니다! – M4rk0444

+0

@ M4rk0444 죄송합니다. 템플릿은 PropertyList와 일치하지만 현재 노드를 복사하지 않고 Property 요소를 처리하는 것으로 바로갑니다. XSLT를 수정하여 바로 수정하겠습니다. –

+0

고마워요! 이것은 나를 많이 도왔습니다! – M4rk0444