2011-02-03 6 views
2

xsl에서 다음을 수행 할 수 있습니다. 요소의 내용을 분할하고 분할을 기반으로 하위 요소를 작성합니다. 일을 더 어렵게 만들려면 가끔 예외가 있습니다 (예 : 노드 4가 분할되지 않음). 각 요소에 대해 하드 코드 된 명시 적 분할없이이 작업을 수행 할 수있는 방법이 있는지 궁금 하네. 다시 말하지만 이것이 가능한지 확실하지 않습니다. 도와 주셔서 감사합니다!xslt는 분할 및 부모 노드 이름을 기반으로 자식을 생성합니다.

원래 XML :

<document> 
    <node> 
    <node-1>hello world1</node-1> 
    <node-2>hello^world2</node-2> 
    <node-3>hello^world3</node-3> 
    <node-4>hello^world4</node-4> 
    </node> 
</document> 

변환 된 XML

<document> 
    <node> 
    <node-1>hello world1</node-1> 
    <node-2> 
     <node2-1>hello</node2-1> 
     <node2-2>world2</node2-2> 
    </node-2> 
    <node-3> 
     <node3-1>hello</node3-1> 
     <node3-2>world3</node3-2> 
    </node-3> 
    <node-4>hello^world4</node-4> 
    </node> 
</document> 

답변

1

다음은 XSL 1.0 솔루션입니다. 나는 샘플 출력에서 ​​node-4의 불일치가 단지 오타라고 추정한다. 그렇지 않으면 node3이 분할 된 이유와 node4가 분할되지 않은 이유를 정의해야합니다.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
    <document> 
     <node> 
     <xsl:apply-templates select="document/node/*"/> 
     </node> 
    </document> 
    </xsl:template> 

    <xsl:template match="*"> 
    <xsl:variable name="tag" select="name()"/> 

    <xsl:choose> 

     <xsl:when test="contains(text(),'^')"> 
     <xsl:element name="{$tag}"> 
      <xsl:element name="{concat($tag,'-1')}"> 
      <xsl:value-of select="substring-before(text(),'^')"/> 
      </xsl:element> 
      <xsl:element name="{concat($tag,'-2')}"> 
      <xsl:value-of select="substring-after(text(),'^')"/> 
      </xsl:element> 
     </xsl:element> 
     </xsl:when> 

     <xsl:otherwise> 
     <xsl:copy-of select="."/> 
     </xsl:otherwise> 

    </xsl:choose> 

    </xsl:template> 

</xsl:stylesheet> 

이 당신이 /document/node에서 같은 수준에 분할하고자하는 모든 노드만큼 작동합니다. 실제 문서 구조가 다른 경우 일치시킬 솔루션을 조정해야합니다.

+0

멋지게 완료되었습니다. 고맙습니다. foreach와 positon()을 사용하여 N 개의 하위 노드를 가질 수 있도록 조금 변경했습니다. 다시 한 번 감사드립니다! – user364939

+0

누군가가 관심이있는 경우를 대비해 대부분의 Jims를 사용하는 최종 솔루션 게시 – user364939

+0

질문에 대한 답은 다음과 같습니다. * 가끔씩 예외가 있습니다 (예 : 노드 4가 분할되지 않음). * –

0

는 XSLT 2.0 사용할 수 있습니까? 그렇다면 <xsl:analyze-string>이 당신의 골목 오른쪽에있는 것처럼 들립니다. 정규 표현식을 기반으로 분할 할 수 있습니다.

자세히 알아 보려면

0

솔루션은 내가 사용 :

<xsl:output omit-xml-declaration="yes" method="xml" indent="yes"/> 
<xsl:preserve-space elements="*"/> 

<xsl:template match="node()|@*" name="identity"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()[1]|@*"/> 
    </xsl:copy> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
</xsl:template> 

<xsl:template match="node()" mode="copy"> 
    <xsl:call-template name="identity"/> 
</xsl:template> 

<xsl:template match="node-2 | node-3" name="subFieldCarrotSplitter"> 
    <xsl:variable name="tag" select="name()"/> 
    <xsl:element name="{$tag}"> 
     <xsl:for-each select="str:split(text(),'^')"> 
      <xsl:element name="{concat($tag,'-',position())}"> 
       <xsl:value-of select="text()"/> 
      </xsl:element> 
     </xsl:for-each> 
    </xsl:element> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
</xsl:template> 

+0

@ user364939 : http://stackoverflow.com/questions/4281431/how-can-i-transform-this-using-keys 질문을 링크하지 않으면 다른 사람들이 추종 축에서 이동하는 것이 이상 할 수 있습니다. 또한 확장 기능이없는 클래식 토크 나이저에 대한 내 대답을 확인하십시오. –

2

일이 까다 만들려면 가끔 예외가 (즉, 노드 4 분할을하지 않음)이 있습니다. 나는 각각 요소에 대해 명시 적 분할 코드없이 하드 코드 할 수있는 방법이 있는지 궁금합니다.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="text()[contains(.,'^')]" name="tokenize"> 
     <xsl:param name="pString" select="concat(.,'^')"/> 
     <xsl:param name="pCount" select="1"/> 
     <xsl:if test="$pString"> 
      <xsl:element name="{translate(name(..),'-','')}-{$pCount}"> 
       <xsl:value-of select="substring-before($pString,'^')"/> 
      </xsl:element> 
      <xsl:call-template name="tokenize"> 
       <xsl:with-param name="pString" 
           select="substring-after($pString,'^')"/> 
       <xsl:with-param name="pCount" select="$pCount + 1"/> 
      </xsl:call-template> 
     </xsl:if> 
    </xsl:template> 
    <xsl:template match="node-4/text()"> 
     <xsl:value-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

출력 :

<document> 
    <node> 
     <node-1>hello world1</node-1> 
     <node-2> 
      <node2-1>hello</node2-1> 
      <node2-2>world2</node2-2> 
     </node-2> 
     <node-3> 
      <node3-1>hello</node3-1> 
      <node3-2>world3</node3-2> 
     </node-3> 
     <node-4>hello^world4</node-4> 
    </node> 
</document> 

: 고전 토크 나이 (사실,이 정규화 된 문자열을 사용

패턴과 일치하는 텍스트 노드,이 더 의미 스타일 시트를 토큰 화하는 빈 항목을 순차적으로 허용). 패턴 일치 및 덮어 쓰기 규칙 (node-4 텍스트 노드 유지).

+0

+1. 더 우수한 솔루션. – Flack

+0

+1 동의합니다. 아주 좋은 솔루션. – user364939

관련 문제