2016-12-06 2 views
0

우리 소프트웨어 용으로 사용자가 편집 할 수있는 XML 구성 파일이 있습니다.이 파일은 Java 응용 프로그램에서 언 마샬링됩니다. 사용자 또는 사용자가 구성 파일 내에서 문자열에 사용할 새 변수를 추가 할 수있게하려고합니다.XSLT 2.0을 사용하여 알 수없는 문자열을 대체하십시오.

나는이 구조로 XML을 가지고

<root> 
    <variables> 
     <key1>foo</key1> 
     <key2>bar</key1> 
     ... 
     <keyn>nthbar</keyn> 
    </variables> 

    <some-tag>PlainText.${key1}.${keyn}.${key2}.MorePlainText</some-tag> 
    <other-tag>${key3}</other-tag> 
</root> 

내가 알려진 키에 대한 값을 대체하기 위해 이런 일을 할 XSLT 2.0을 사용할 수 있음을 알고 있어요 :

<xsl:variable name="key1" select="root/variables/key1/text()" /> 
<xsl:variable name="key2" select="root/variables/key1/text()" /> 
... 
<xsl:variable name="keyn" select="root/variables/key1/text()" /> 

<xsl:template match="text()"> 
    <xsl:value-of select="replace(replace(replace(., '\$\{val1\}', $key1), '\$\{val2\}', $key2), '\$\{valn\}', $keyn)" /> 
</xsl:template> 

말썽을 이것은 매우 유연하지 않다는 것입니다. 새 replace()는 새 키가 추가 될 때마다 기존 replace() 호출을 래핑해야하며 새 변수는 해당 xsl 파일에서 선언해야합니다.

XML 파일의 다른 위치에서 $ {keyn}과 같은 태그를 사용하여 XSLT를 사용하여 value와 같은 태그를 참조하는 매끄러운 방법이 있습니까?

답변

1

당신은 당신의 variables/* 요소에 맞게 키를 사용할 수 있으며 텍스트 노드에 {$var}을 찾기 위해 analyze-string를 사용할 수 있습니다

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 

    <xsl:key name="variables" match="variables/*" use="local-name()"/> 

    <xsl:variable name="main-root" select="/"/> 

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

    <xsl:template match="root/variables"/> 

    <xsl:param name="variable-pattern" as="xs:string">\$\{(\w+)\}</xsl:param> 

    <xsl:template match="text()"> 
     <xsl:analyze-string select="." regex="{$variable-pattern}"> 
      <xsl:matching-substring> 
       <xsl:value-of select="key('variables', regex-group(1), $main-root)"/> 
      </xsl:matching-substring> 
      <xsl:non-matching-substring> 
       <xsl:value-of select="."/> 
      </xsl:non-matching-substring> 
     </xsl:analyze-string> 
    </xsl:template> 

</xsl:stylesheet> 
내가 일치가 발견되는 경우 오류를 높이기 위해 더 좋을 거라 생각

하지만, key('variables', regex-group(1), $main-root)은 (는) 정의가 없습니다.

<xsl:template match="text()"> 
    <xsl:analyze-string select="." regex="{$variable-pattern}"> 
     <xsl:matching-substring> 
      <xsl:variable name="var-match" select="key('variables', regex-group(1), $main-root)"/> 
      <xsl:choose> 
       <xsl:when test="$var-match"> 
        <xsl:value-of select="$var-match"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:message select="concat('No match found for $', regex-group(1))"/> 
       </xsl:otherwise> 
      </xsl:choose>   
     </xsl:matching-substring> 
     <xsl:non-matching-substring> 
      <xsl:value-of select="."/> 
     </xsl:non-matching-substring> 
    </xsl:analyze-string> 
</xsl:template> 
+0

고마워요! 내가해야만하는 유일한 변경 사항은 루트를 실제 루트 태그로 바꾸고 태그 내용이 출력으로 복사되었는지 확인하는 것입니다. - 그럴 필요가 있습니다 ;-) – circleofconfusion

+1

이것은 매우 동일하지 않습니다. 원래 코드로. 원래의 경우,'$ {key1}'을 대체하면'$ {key2} '를 포함하는 문자열이 생성되고, 그 키에서 더 많은 치환이 일어납니다. @ MartinHonnen의 해결책에서 대체물의 출력은 더 이상 대체 할 수 없습니다. –