2013-11-04 4 views
2

파일 메이커 데이터베이스에서 레코드를 그룹화하려고합니다. XSLT를 사용하여 변환하는 옵션을 사용하여 XML로 내보내고 있습니다.XSLT에서 노드 값을 기준으로 XML 요소를 그룹화하는 방법은 무엇입니까?

나는 다른 게시물을 검색하고 읽었으며, 내가하고 싶은 것을 정확하게 커버하지는 않는다고 생각합니다.

는 XML의 발췌 :

<?xml version="1.0" encoding="UTF-8"?> 
<!-- This grammar has been deprecated - use FMPXMLRESULT instead --> 
<FMPDSORESULT xmlns="http://www.filemaker.com/fmpdsoresult"> 
    <ERRORCODE>0</ERRORCODE> 
    <DATABASE>Artpostersnbbs.fp7</DATABASE> 
    <LAYOUT /> 
    <ROW MODID="19" RECORDID="11116"> 
     <Art_Type>Poster</Art_Type> 
     <Location>1</Location> 
     <Line1>ELEVATOR 
        MACHINE 
        ROOM 
        107</Line1> 
    </ROW> 
    <ROW MODID="19" RECORDID="11116"> 
     <Art_Type>Poster</Art_Type> 
     <Location>2</Location> 
     <Line1>ELEVATOR 
        MACHINE 
        ROOM 
        107</Line1> 
    </ROW> 
    <ROW MODID="19" RECORDID="11116"> 
     <Art_Type>Poster</Art_Type> 
     <Location>3</Location> 
     <Line1>ELEVATOR 
        MACHINE 
        ROOM 
        107</Line1> 
    </ROW> 
</FMPDSORESULT> 

내가 그룹 ART_TYPE와 LINE1 모두 일치하는 각 레코드를 원한다.

<ROW MODID="19" RECORDID="11116"> 
    <Art_Type>Poster</Art_Type> 
    <Location>1 2 3</Location> 
    <Line1>ELEVATOR 
      MACHINE 
      ROOM 
      107 
    </Line1> 
</ROW> 

주시면 감사하겠습니다 시작하는 방법에 어떤 도움 : 그것은 하나에 경기에서 위치를 추가해야합니다 그룹화 한 후이 같아야하므로으로 분류된다. 또한 좋은 xslt 1.0 테스트 프로그램이 있습니까? 사전에

감사합니다!

편집 :

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="artTypeNames" match="ROW" use="Art_Type" /> 
    <xsl:key name="artCopy" match="ROW" use="Line1" /> 
    <xsl:template match="FMPDSORESULT"> 
    <xsl:for-each select="ROW[count(. | key('artTypeNames', Art_Type)[1]) = 1]"> 
     <xsl:sort select="Art_Type" /> 
     <xsl:value-of select="Art_Type" /> 
     <xsl:for-each select="key('artTypeNames', Art_Type)"> 
      <xsl:sort select="Art_Type" /> 
      <xsl:value-of select="Art_Type" /> 
     </xsl:for-each> 
    </xsl:for-each> 

    <xsl:apply-templates/> 
    </xsl:template> 
</xsl:stylesheet> 

내가 온라인 XML 변압기에 XML과 XSLT를 입력 : 내가 생각 해낸 것을 읽고 그래서 http://www.jenitennison.com/xslt/grouping/muenchian.html

: 나는 muenchian 그룹을 지적하고이 사이트를 발견 'XSLT is invalid'오류가 발생합니다.

이것은 실망 스럽습니다.

EDIT2가 :에 의해 다음

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fm="http://www.filemaker.com/fmpdsoresult"> 

<xsl:template match="fm:FMPDSORESULT"> 
    <xsl:apply-templates select="fm:ROW[count(. | key('lineData', fm:Line1)[1]) = 1]"> 
    </xsl:apply-templates> 
</xsl:template> 

<xsl:template match="fm:ROW"> 
    <xsl:copy> 
     <xsl:apply-templates select="fm:Art_Type" /> 
     <fm:Location> 
      <xsl:apply-templates select="key('artTypeNames', fm:Art_Type)/fm:Location" /> 
     </fm:Location> 
     <xsl:apply-templates select="fm:Line1" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="fm:Location"> 
    <xsl:if test="position() > 1">-</xsl:if> 
    <xsl:value-of select="." /> 
</xsl:template> 

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

이 그룹화 Art_Type과 : 팀의 도움으로 나는 변환 적절한 XSLT를 구축 할 수 있었다 Line1 텍스트이지만 위치 번호가 추가됩니다. 이런 그들 모두에 다음 줄 1 텍스트가 다른 경우

<ROW xmlns="http://www.filemaker.com/fmpdsoresult"> 
<Art_Type>Poster</Art_Type> 
<fm:Location xmlns:fm="http://www.filemaker.com/fmpdsoresult" xmlns="">1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34</fm:Location> 
<Line1>CUSTODIAL 
    LOUNGE 

    117A 
</Line1> 
</ROW> 
<ROW xmlns="http://www.filemaker.com/fmpdsoresult"> 
<Art_Type>Poster</Art_Type> 
<fm:Location xmlns:fm="http://www.filemaker.com/fmpdsoresult" xmlns="">1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34</fm:Location> 
<Line1>STORAGE 
    ROOM 

    117B 
</Line1> 
</ROW> 

, 그것은 다른 그룹으로 추가해야합니다.

+2

간단한 XSLT 온라인 도구 당신을 찾고 있다면 http://xslttest.appspot.com/ – Hash

+0

감사합니다. 일단 xslt lol을 사용하는 방법을 알아 내면 유용 할 것입니다. – clrx

+0

XSLT에서 google "기본 네임 스페이스"를 원할 수도 있습니다. –

답변

3

주석에 언급 된 한 가지 문제점은 네임 스페이스와 관련이 있다는 것입니다.

<FMPDSORESULT xmlns="http://www.filemaker.com/fmpdsoresult"> 

이 해당 요소를 의미하며 (아래 낮은 오버 쟁이하지 않는 한) 그 아래의 모든 하위 요소는 해당 네임 스페이스에 속하는 : 당신의 XML에서 네임 스페이스 선언이있다. 하지만 XSLT에는 네임 스페이스에 대한 언급이 없으므로 XSLT는 NO 네임 스페이스에 속한 요소를 찾고 있습니다.

XSLT에서 네임 스페이스를 선언 한 다음 원본 XML의 요소를 참조 할 때 네임 스페이스 접두사를 사용해야합니다.

<xsl:stylesheet version="1.1" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fm="http://www.filemaker.com/fmpdsoresult"> 
    <xsl:key name="artTypeNames" match="fm:ROW" use="fm:Art_Type" /> 
    <xsl:template match="fm:FMPDSORESULT"> 

XSLT 샘플의 경우, 코드 조각을 보여주고 있지만 시도 할 때 어떤 오류도 발생하지 않습니다. 그룹화가 정확합니다 (행 Art_Type). 기존 요소를 복사하는 코드는 누락되었습니다.

<xsl:for-each select="fm:ROW[count(. | key('artTypeNames', fm:Art_Type)[1]) = 1]"> 
    <xsl:sort select="fm:Art_Type" /> 
    <xsl:copy> 
     <xsl:copy-of select="@*" /> 
     <xsl:copy-of select="fm:Art_Type" /> 

그래서,이 조각 복사 기존 ROW 요소의 속성, 그리고 (그룹의 모든 요소에 대해 동일합니다) 다음 Art_Type 요소입니다.

분명히 Art_Type 그룹의 모든 요소에 대해 동일하기 때문에 내부를위한 각 루프의 종류에 대한 필요가 없었다이 (완전한) XSLT에게

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fm="http://www.filemaker.com/fmpdsoresult"> 
    <xsl:key name="artTypeNames" match="fm:ROW" use="fm:Art_Type" /> 

    <xsl:template match="fm:FMPDSORESULT"> 
    <xsl:for-each select="fm:ROW[count(. | key('artTypeNames', fm:Art_Type)[1]) = 1]"> 
     <xsl:sort select="fm:Art_Type" /> 
     <xsl:copy> 
      <xsl:copy-of select="@*" /> 
      <xsl:copy-of select="fm:Art_Type" /> 
      <fm:Location> 
      <xsl:for-each select="key('artTypeNames', fm:Art_Type)"> 
       <xsl:if test="position() > 1">-</xsl:if> 
       <xsl:value-of select="fm:Location" /> 
      </xsl:for-each> 
      </fm:Location> 
      <xsl:copy-of select="fm:Line1" /> 
     </xsl:copy> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

참고하십시오.

편집 : 그룹을 구성하는 요소를 결정하기 위해 두 필드를 확인하려면 연결 키를 사용해야합니다. 귀하의 경우, Art_Typefm : Line1을 모두 확인하기 때문에 키가 다음과 같이 보일 수 있습니다.

<xsl:key name="artTypeNames" match="fm:ROW" use="concat(fm:Art_Type, '||', fm:Line1)" /> 

참고로 '||' 이리. 확인중인 요소 중 하나에 표시되지 않는 한 아무 것도 될 수 있습니다.

이 키를 사용하려면 이전과 비슷한 방식으로 요소를 연결 한 값을 사용하면됩니다. 예를

<xsl:apply-templates select="fm:ROW[count(. | key('artTypeNames', concat(fm:Art_Type, '||', fm:Line1))[1]) = 1]"> 

참고를 들어,이 XSL을 사용하는 것이 더 좋다 : 대신 XSL의 템플릿 적용을위한-각 만 들여 쓰기를 줄일 경우.

너무

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fm="http://www.filemaker.com/fmpdsoresult"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="artTypeNames" match="fm:ROW" use="concat(fm:Art_Type, '||', fm:Line1)"/> 

    <xsl:template match="fm:FMPDSORESULT"> 
     <xsl:apply-templates select="fm:ROW[count(. | key('artTypeNames', concat(fm:Art_Type, '||', fm:Line1))[1]) = 1]"> 
     <xsl:sort select="fm:Art_Type"/> 
     </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="fm:ROW"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates select="fm:Art_Type"/> 
     <fm:Location> 
      <xsl:apply-templates select="key('artTypeNames', concat(fm:Art_Type, '||', fm:Line1))/fm:Location"/> 
     </fm:Location> 
     <xsl:apply-templates select="fm:Line1"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="fm:Location"> 
     <xsl:if test="position() &gt; 1">-</xsl:if> 
     <xsl:value-of select="."/> 
    </xsl:template> 

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

가 대신 XSL의 기존 요소를 복사 할 XSLT identity transform의 사용을주의이 XSLT를보십시오 : 복사의

+0

나는 stackoverflow와 다른 곳에서 웹상의 다른 예제들을보고 있었고 예제들은 네임 스페이스를 사용하여 XML 엘리먼트에 접근하는 것을 보여주지 않았으므로 나는 그것을 생략해야한다고 생각했다.귀하의 XSLT를 시도하고 그것은 Art_Type 및 Line1, 단지 Art_Type을 테스트하지 않는다는 것을 제외하고는 작동합니다. 위에서 언급 한 XML은이 질문에 대한 작은 스 니펫 일뿐입니다. – clrx

+0

그룹을 결정할 때 두 가지 요소를 확인하는 방법을 보여주기 위해 내 대답을 편집했습니다. –

+0

잘 작동하고 XSLT의 작동 방식을 훨씬 잘 이해할 수 있습니다. 그냥 좀 더 함께 놀 필요가 있습니다. Liquid XML은 루트 요소가 여러 개 있다고 말하면서 오류를 일으켰습니다. 루트 요소 가 제거되었으므로 이제는 루트 요소 만이 있기 때문에 가정합니다. 루트 요소를 제거하거나 루트 요소를 다시 읽지 못하게하는 방법은 무엇입니까? – clrx

4

XSLT 2.0을 사용하는 경우 xsl:for-each-group에 대한 정보를 찾으십시오. 1.0을 사용하는 경우 'Muenchian grouping'에 대한 정보를 찾으십시오.

+0

그래서 나는 이것을 발견했다 : http://www.jenitennison.com/xslt/grouping/muenchian.html 그리고 그것은 Muechian 그룹핑의 좋은 실행을 제공한다. 그러나 나는 정확하게 그것을 정확하게하고 있다고 확신하지 못한다. – clrx

관련 문제