2010-02-01 1 views
0

왼쪽의 잎에 주어진 이름으로 노드를 추가합니다. 예를 들어 ,XSLT. 주어진 이름으로 가장 왼쪽 잎에 노드를 추가하는 방법?

<root> 
    <aaa name="a"> 
    <aaa name="x"/> 
    </aaa> 
    <aaa name="b"> 
    <aaa name="y"> 
     <aaa name="z"/> 
    </aaa> 
    </aaa> 
    <aaa name="c"> 
    <aaa name="z"/> 
    </aaa> 
</root> 

주어 NAME = "Z"주어진 새로운 노드 <aaa name="w">이다. 당신이 뭔가를 시작할 수

<root> 
    <aaa name="a"> 
    <aaa name="x"/> 
    </aaa> 
    <aaa name="b"> 
    <aaa name="y"> 
     <aaa name="z"> 
     <aaa name="w"/> 
     </aaa> 
    </aaa> 
    </aaa> 
    <aaa name="c"> 
    <aaa name="z"/> 
    </aaa> 
</root> 
+0

원래 나무 '이름 ='z'' 2 개 노드가 가진 첫번째 잎. 새 노드를 추가 할 노드를 지정하는 방법은 무엇입니까? –

+0

"가장 왼쪽 잎" – Alexander

답변

0

: 새로운 나무는 다음과 같은 형식이어야합니다

왼쪽하여 가장 큰 깊이와 'Z'노드를 의미
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/"> 
    <xsl:apply-templates /> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:if test="@name='z'"> 
     <aaa name="w"/> 
     </xsl:if> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
2

경우 먼저 정의 할 수 있습니다 변수는 가장 왼쪽의 'Z'의 깊이를 해결하고,이를 사용하여 같은 깊이

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <!-- Work out depth of left most 'z' node --> 
    <xsl:variable name="LeftMost"> 
     <xsl:for-each select="//*[@name='z']"> 
     <xsl:sort select="count(ancestor::*)" order="descending"/> 
     <xsl:if test="position() = 1"> 
      <xsl:value-of select="count(ancestor::*)"/> 
     </xsl:if> 
     </xsl:for-each> 
    </xsl:variable> 
    <xsl:template match="/"> 
     <xsl:apply-templates/> 
    </xsl:template> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:if test="@name='z' and count(ancestor::*) = $LeftMost"> 
      <aaa name="w"/> 
     </xsl:if> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

에서 노드와 일치 할 때이 'Z'를했다면 그런 다음, 'w'노드를 추가하는 같은 노드 두 노드 모두 'w'노드가 주어지면 결국 깊어집니다.

또 다른 방법은 generate-id()를 사용하여 주먹 'z'의 ID를 최대 깊이로 가져온 다음 노드를 동일한 ID와 일치시킬 때 'w'를 추가하는 것입니다. 그러면 가장 큰 깊이에서 발견되는 첫 번째 'z'노드에만 'w'노드가 추가됩니다.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:variable name="LeftMost"> 
     <xsl:for-each select="//*[@name='z']"> 
     <xsl:sort select="count(ancestor::*)" order="descending"/> 
      <xsl:if test="position() = 1"> 
       <xsl:value-of select="generate-id()"/> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:variable> 
    <xsl:template match="/"> 
     <xsl:apply-templates/> 
    </xsl:template> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
      <xsl:if test="@name='z' and generate-id() = $LeftMost"> 
       <aaa name="w"/> 
      </xsl:if> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+0

+1. BTW : 이것은 행마다 * 정확히 * 귀하의 게시물을 먼저 읽지 않고 나온 해결책입니다. – Tomalak

+1

아! 나는 가장 왼손잡이가 무엇을 잘못 이해했는지 보았다. 노드의 첫 번째 발생을 얻으려면 예제에서 'ansestor'를 'preceding'로 바꿉니다. –

2

@Tim C's variable based approach의 변형이 같은 <xsl:key> 및 앞 축, 포함합니다 :이 방법의

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
    <xsl:key 
    name="kCountPreceding" match="aaa[@name='z']" 
    use="count(preceding::aaa[@name='z'])" 
    /> 
    <xsl:variable name="vLeftMostId" select=" 
    generate-id(key('kCountPreceding', 0))" 
    /> 

    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*" /> 
     <xsl:if test="generate-id() = $vLeftMostId"> 
     <aaa name="w" /> 
     </xsl:if> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

단점은, 어떤 변수가 일치 식에 허용됩니다. 이것은 이것이 동적으로 만들어 질 수 없음을 의미하며, 키의 match="aaa[@name='z']"은 하드 코딩되어야합니다.

0

왜 선행 축을 사용하지 않습니까?

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="/"> 
    <xsl:apply-templates /> 
    </xsl:template> 
    <xsl:template match="*[@name='z' and not(preceding::*[@name='z'])]"> 
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <aaa name="w" /> 
     <xsl:apply-templates /> 
    </xsl:copy> 
    </xsl:template> 
    <xsl:template match="*"> 
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates /> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

동의어, 가장 왼쪽의 잎은 문서 순서의 첫 번째 잎이 아닙니까? 의 첫 번째 잎이 문서 순서

<xsl:for-each select="/descendant::*[@name='z' and not(*)][1]"> 
    ... 
    <aaa name="w" /> 
    ... 
</xsl:for-each> 
+0

예, 주어진 이름의 첫 번째 잎 – Alexander

0

가장 왼쪽의 잎 그렇지?

예, 지정된 이름

+0

@ 알렉산더 : 포럼처럼 스택 오버플로를 사용하지 마십시오. 아래 부분은 질문에 대한 답변이며, 후속 게시물이나 댓글은 아닙니다. 자신 만의 질문에 답하지 않는 한 (어떤 것이 좋을지), 코멘트 기능을 사용하거나 질문을 수정하여 누락 된 세부 사항을 추가하십시오. 이 게시물을 삭제하십시오. – Tomalak

관련 문제