2011-07-04 9 views
3

를 사용하여 XML 파일의 일부를 추출네임 스페이스를 제거하고 XSL

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes" omit-xml-declaration="yes" /> 
    <xsl:template match="/"> 
     <xsl:copy-of select="//city"> 
     </xsl:copy-of> 
    </xsl:template> 
</xsl:stylesheet> 

위의 XSL은 위의 입력 XML에 대해 작동하지 않습니다. 이름 공간이 추가 된 경우 : 다음과 같이 :

<country xmlns="http://india.com/states" version="1.0"> 
    <state> 
     <city> 
      <name>DELHI</name>    
     </city> 
    </state> 
</country> 

나는 이름 공간을 복사 할 도시 요소와 함께 제거해야합니다.

도움을 주시면 감사하겠습니다. 감사합니다.

+0

좋은 질문, +1. 완전하고 간단하며 쉬운 해결책은 내 대답을 참조하십시오. 자세한 설명도 제공됩니다. –

+0

"다른 John"의 수정 된 질문에 대한 내 대답을 업데이트했습니다. 이것이 당신이라면, SO에게 연락하여 두 신원을 합치십시오. –

+0

내 대답이 도움이 되었습니까? –

답변

2

XPath, XML 및 XSLT에서 가장 자주 묻는 질문입니다. "기본 네임 스페이스 및 XPath 식"을 검색하십시오. 용액로서는

: 원하는 결과를 제작

<country xmlns="http://india.com/states" version="1.0"> 
    <state> 
     <city> 
      <name>DELHI</name> 
     </city> 
    </state> 
</country> 

:

이 변환이 제공된 XML 문서에인가

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:x="http://india.com/states"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="*"> 
    <xsl:element name="{name()}"> 
    <xsl:copy-of select="@*"/> 
    <xsl:apply-templates/> 
    </xsl:element> 
</xsl:template> 


<xsl:template match="*[not(ancestor-or-self::x:city)]"> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

<city> <name>DELHI</name> </city> 

설명는 :

  1. 의 XPath에서 아무것도없는 요소 이름은 항상 "네임 스페이스"에있을 considerd된다. 그러나 제공된 XML. 서의 모든 요소 이름은 비어 있지 않은 네임 스페이스 (기본 네임 스페이스 "http://india.com/states")에 있습니다. 따라서 //city은 XML 문서에 네임 스페이스가없는 요소가 없으므로 노드를 선택하지 않고 은 이 네임 스페이스에 바인딩되어 있습니다. "http://india.com/states"은 모든 도시 요소 (즉, 네임 스페이스 "http://india.com/states")를 선택합니다.

  2. 이 변환에는 두 개의 템플릿이 있습니다. 첫 x 째 템플리트는 요소를 일치시키고이를 다시 작성하지만 네임 스페이스가 없 습니 다. 또한 모든 속성을 복사 한 다음 템플리트를이 요소의 하위 노드에 적용합니다.

  3. 두 번째 템플릿은 city 요소의 조상이 아니거나 그 자체가 city 요소 인 모든 요소에 대해 첫 번째 템플릿보다 첫 번째 템플릿을 우선합니다. 이 작업은 모든 자식 노드에 템플릿을 적용하는 것입니다.

UPDATE는 :

위해 에서
<country xmlns="http://india.com/states" version="1.0"> 
     <state> 
      <city> 
       <name>DELHI</name> 
      </city> 
     </state> 
     <state2> 
      <city2> 
       <name2>MUMBAI</name2> 
      </city2> 
     </state2> 
</country> 

하지에 : 영업 이익은 새로운 수정 된 XML 문서의 처리 결과 비 원하는 텍스트가 이유를 묻는 질문을 수정 한 "MUMBAI"텍스트를 생성하면 위의 변환은 약간 수정되어 x:city 상위 노드가없는 텍스트 노드를 무시 (복사 제외)해야합니다.

<xsl:template match="text()[not(ancestor::x:city)]"/> 

전체 변환 이제된다 : 이러한 목적을 위해, 우리는 다음과 같은 한 줄, 빈 템플릿 추가

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:x="http://india.com/states"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="*"> 
     <xsl:element name="{name()}"> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="*[not(ancestor-or-self::x:city)]"> 
     <xsl:apply-templates/> 
    </xsl:template> 

    <xsl:template match="text()[not(ancestor::x:city)]"/> 
</xsl:stylesheet> 

을하고 결과는 여전히 하나의 올바른 원하는입니다 :

<city> 
    <name>DELHI</name> 
</city> 
0

템플릿을 사용하여 원하는 출력을 얻을 수 있습니다.

<xsl:template match="*[not(ancestor-or-self::x:*[starts-with(name(),'city')])]"> 
    <xsl:apply-templates/> 
</xsl:template> 

하거나 제공하여 새로운 입력에 마이크로 소프트 (R) XSLT 프로세서 버전 4.0으로 테스트

<xsl:template match="/"> 
    <xsl:apply-templates select="//x:*[starts-with(name(),'city')]"/> 
</xsl:template> 

:

<city> 
    <name>DELHI</name> 
</city> 
<city2> 
    <name2>MUMBAI</name2> 
</city2> 
관련 문제