2009-04-30 3 views
4

XML 문서에서 변환을 시도하고 있습니다.공백 xmlns = ""가져 오기에서의 특성

<StructureA xmlns="http://..."> 

StructureA & :

<xsl:template match="/"> 
    <xsl:choose> 
    <xsl:when test="/databean/data[@id='pkhfeed']/value/text()='200'"> 
     <xsl:call-template name="StructureA"> 
     <xsl:with-param name="structure" select="//databean" /> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:call-template name="StructureB"> 
     <xsl:with-param name="structure" select="//databean" /> 
     </xsl:call-template> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

StructureA 또는 StructureB가 다음 자신의 네임 스페이스와 schemaLocations로 만들어집니다 내 XML 변환은 특정 요소의 값에 따라 기본 요소의 두 가지 유형이 발생할 수 있습니다 B는 몇 가지 공통 요소를 공유하므로 두 구조에 템플릿이 포함 된 별도의 파일 "xmlcommon.xslt"에 정의되어 있습니다. 이 xmlcommon 파일에는 StructureA 또는 StructureB에 정의 된 네임 스페이스에서 사용할 수 있도록 정의 된 기본 네임 스페이스가 없습니다. 내 변환을 실행할 때, 어떤 템플릿 빈의 xmlns의 일반적인 파일 결과에서 가져온 속성 : 유효성을 검사 할 때, 빈 공간은 다음 대신 올바른 부모 중 하나가 사용됩니다

<StructureA xmlns="http://..."> 
    <SharedElement xmlns="">Something</SharedElement> 
</StructureA> 

. 누구나 공통 파일에서 빈 xmlns 속성을 추가하지 않고 템플릿을 중지 할 수있는 방법을 알고 있습니까?

다음은 일반적인 파일에서 코드 조각입니다 :

<xsl:stylesheet version="1.0" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template name="ControlledListStructure"> 
    <xsl:param name="xmlElem" /> 
    <xsl:param name="structure" /> 

    <xsl:element name="{$xmlElem}"> 
     <!-- Blah blah blah --> 
    </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

답변

9

실현하기 위해 중요한 것은 스타일 시트는 결과 트리에 추가하는 각 요소의 이름을 지시한다는 것입니다. 요소의 이름은 로컬 이름과 네임 스페이스 URI의 두 부분으로 구성됩니다. 위의 코드에서 로컬 이름 ($xmlElem의 값)을 제공하지만 네임 스페이스 URI를 지정하지 않으면 기본적으로 빈 문자열이됩니다. (실제로는 스타일 시트 모듈의 기본 네임 스페이스를 사용하며 아무 것도 없기 때문에 빈 문자열입니다.) 즉, 은 네임 스페이스가 아닌입니다. 문서를 직렬화 할 때 XSLT 프로세서에는 xmlns="" 선언이 포함되어 있어야 최상위에 표시되는 기본 네임 스페이스를 표시 할 수 없습니다. 그렇지 않으면 요소는 네임 스페이스를 사용하게됩니다.이 네임 스페이스는 스타일 시트가 지시하지 않은 것입니다. 이 문제를 해결하는 가장 작은 방법은 $xmlElem처럼 다른 매개 변수 (예 : $namespaceURI)를 추가하는 것입니다. 그런 다음 당신이 쓰는 것 :

<xsl:element name="{$xmlElem}" namespace="{$namespaceURI}"> 

을 지금, 결과 요소는 (그 기본 네임 스페이스를 해제 선언을 제거하는 효과를 가질 것이다)에 걸릴 당신이 그것을 말해 어떤 공간에 걸립니다.

귀하의 질문에 답변 해주십시오. 무료 보너스 자료로 다음을 제공합니다. ;-)

가치 비교에서 text() 노드 테스트를 제거해야합니다. 매우 드물게 텍스트 노드의 값을 직접 비교해야합니다. 대신 요소 자체의 문자열 값 (모든 자손 텍스트 노드의 문자열 값을 연결 한 것으로 정의 됨)을 비교할 수 있습니다. 즉,이과 같습니다

<xsl:when test="/databean/data[@id='pkhfeed']/value = '200'"> 

이 방법은 거기에 숨어 ​​의견이 있다면 코드가 중단되지 것입니다 그 일의 장점 :이 경우

<value>2<!--test-->00</value> 

, 두 가지가 있습니다 텍스트 노드 ("2"와 "00"). 원래 테스트는 "200"과 같은지 확인하기 때문에 실패합니다.이 경우에 일어날 가능성은별로 없지만, 텍스트 노드 자식과는 달리 요소의 문자열 값을 테스트하는 것이 좋은 의도입니다.

마지막으로 템플릿 규칙 및 XPath 컨텍스트에 대해 배우는 것이 좋습니다. 가능한 경우 <xsl:choose>, <xsl:call-template><xsl:with-param>을 피하는 경향이 있습니다. 템플릿 규칙은 XSLT의 추악하고 장황한 부분을 피할 수 있습니다.

<xsl:template match="/databean[data[@id='pkhfeed']/value = '200']" priority="1"> 
    <StructureA xmlns="http://..."> 
    ... 
    </StructureA> 
</xsl:template> 

<xsl:template match="/databean"> 
    <StructureB xmlns="http://..."> 
    ... 
    </StructureB> 
</xsl:template> 

<xsl:call-template> 계속 사용하더라도, 현재 노드가 호출 된 템플릿에 변경되지 않습니다로서, 그 $structure 매개 변수를 전달 할 필요가 없습니다. 현재 노드가 여전히 "/"(문서 노드)이기 때문에 StructureA 또는 StructureB 템플릿 중 하나에서 쉽게 //databean (또는 /databean, 나는 그것이 의미하는 것으로 의심됩니다)에 액세스 할 수 있습니다.

는 XSLT의 핵심 처리 모델, 그것의 가장 강력한 기능 (템플릿 규칙)에 관심이있는 경우

후 내 XSLT 1.0 포켓 참조에서 "How XSLT Works", 무료 샘플 장을 확인하는 것이 좋습니다.

귀하가 협상 한 것 이상이라도 이것이 도움이 되었기를 바랍니다.

+0

좋은 설명, Evan. 추가 할 것이 아무것도 없습니다. +1. 에 오신 것을 환영합니다. –

+0

감사합니다. 그것은 큰 도움이됩니다 :) 그리고 추가 정보를 주셔서 감사합니다. XSLT를 자주 만지지는 않기 때문에 더 나은 방법으로 일을하는 것이 좋다. –