2010-02-19 9 views
0

대략 주 나이 I asked the question here 및 도움을 얻었다. 이제 내 질문에 계속됩니다. 원래 XML을 텍스트 파일로 변환해야했습니다. 다음은 샘플 XML 파일입니다 :XSLT를 사용하여 XML 특성 존재를 확인하는 방법

<DOC xsi:noNamespaceSchemaLocation="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<DOC_REQUISITES DOC_DATE="2009-04-23" DOC_NO="99999999"/> 
<DOCID TradeDate="2009-04-23" Weekday="Monday" MainFirmId="ZXC0000" FirmName="Firm Name" FirmINN="1234567899"> 
    <FIRM FirmID="FirmId"> 
     <CURRENCY CurrencyId="USD"> 
     <DEPARTMENT DepartmentId="ABCD" DepName="Department Name1"> 
      <SETTLEDATE SettleDate="2009-04-23"> 
       <SECURITY SecurityId="QAZ" SecShortName="SecName1" SecurityType="dc" FaceValue="5"> 
        <TRDACC TrdAccId="ABC00000"> 
         <RECORDS RecNo="1" TradeNo="111" TradeTime="15:15:16" Price="10" Quantity="50" Value="500"/> 
        </TRDACC> 
        <TRDACC TrdAccId="SDC00000"> 
         <RECORDS RecNo="2" TradeNo="112" TradeTime="15:15:16" Price="10" Quantity="50" Value="500"/> 
         <RECORDS RecNo="3" TradeNo="113" TradeTime="15:15:16" Price="20" Quantity="10" Value="200"/> 
        </TRDACC> 
       </SECURITY> 
       <SECURITY SecurityId="WSX" SecShortName="SecName2" SecurityType="dc" FaceValue="1"> 
        <TRDACC TrdAccId="ABC00000"> 
         <RECORDS RecNo="4" TradeNo="114" TradeTime="15:15:13" Price="2" Quantity="1" Value="2"/> 
        </TRDACC> 
       </SECURITY> 
      </SETTLEDATE> 
     </DEPARTMENT> 
     <DEPARTMENT DepartmentId="CBSD" DepName="Department Name2"> 
      <SETTLEDATE SettleDate="2009-05-20"> 
       <SECURITY SecurityId="RFV" SecShortName="SecName3" SecurityType="dc" FaceValue="2"> 
        <TRDACC TrdAccId="SDC00000"> 
         <RECORDS RecNo="5" TradeNo="115" TradeTime="15:15:13" Price="100" Quantity="10" Value="1000"/> 
        </TRDACC> 
       </SECURITY> 
      </SETTLEDATE> 
     </DEPARTMENT> 
    </CURRENCY> 
    </FIRM> 
</DOCID> 

내 원하는 출력은 다음과 같습니다

2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,2009-04-23,QAZ,SecName1,dc,5,ABC00000,1,111,15:15:16,10,50,500 
2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,2009-04-23,QAZ,SecName1,dc,5,SDC00000,2,112,15:15:16,10,50,500 
2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,2009-04-23,QAZ,SecName1,dc,5,SDC00000,3,113,15:15:16,20,10,200 
2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,2009-04-23,WSX,SecName2,dc,1,ABC00000,4,114,15:15:13,2,1,2 
2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,CBSD,Department Name2,2009-05-20,RFV,SecName3,dc,2,SDC00000,5,115,15:15:13,100,10,1000 

이 XSLT 나를 위해 배치되고 그냥 잘 작동합니다. 정말 감사. 생성 된 출력 파일은 나중에 데이터베이스에로드 될 것입니다 :

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="/DOC/DOCID/FIRM/CURRENCY/DEPARTMENT/SETTLEDATE/SECURITY/TRDACC"/> 
    </xsl:template> 

<xsl:template match="TRDACC"> 
    <!--Select all of the attribute values from the preceding DOC_REQUISITES attibutes, TRDACC ancestor elements, the current element, and all of it's descendants and then apply-templates to those attributes --> 
    <xsl:apply-templates select="preceding::DOC_REQUISITES/@* | ancestor::*[not(local-name()='DOC')]/@* | @* | descendant::*/@*"/> 
    <!--Adds a carriage return at the end of the line --> 
    <xsl:value-of select="'&#10;'"/> 
</xsl:template> 

<!--Template match for attributes that emits the attribute value and a ',', except for the last one --> 
<xsl:template match="@*[.!='']"> 
    <xsl:value-of select="."/> 
    <xsl:if test="position()!=last()">,</xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

여기 내 질문이다. 테이블의 열은 xml 파일 특성에 해당합니다. 일부 열은 Null을 허용했습니다. 이는 일부 속성을 생략 할 수 있음을 의미합니다. 예를 들어, attr. DOC_NO은, 평일은 SettleDate는 RECNO 출력 기록이이 같은 모습이어야 존재하지 : 즉

2009-04-23,,2009-04-23,,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,,QAZ,SecName1,dc,5,ABC00000,,111,15:15:16,10,50,500 

나는 각 속성의 존재를 확인해야합니다. 나는 그것을 해결하려고하지만 내 xslt 지식은 매우 제한되어 있습니다. 도와주세요. 감사.

+0

문서에 속성이 있습니까 (예 :'SettleDate = ""') 값이 없거나 문서에서 누락 된 속성입니까? –

+0

속성이 누락되었을 수 있습니다. – klipa

답변

0

상세한 분석없이, 나는 그래서 회신 주셔서 감사합니다,이

<xsl:template match="@*"> 
+0

짐, 답장을 보내 주셔서 감사합니다. 나는 같은 것을 할 필요가 생각하는 , , 가능한 속성마다 그래서 존재한다면 그것은 단지 ","가 아니라면 레코드에 가치를 넣을 것입니다. 그러나 나는 이것을 이미 XSLT에 삽입하는 방법을 모른다. – klipa

+0

attribute = ""인 경우 작업을 제안하지만 속성 존재 여부를 확인해야합니다. 왜냐하면 테이블 열과 일치하는 가능한 속성 목록이 있고 XML 입력 파일에 모든 속성이 없을 수도 있기 때문입니다. – klipa

0

짐처럼 보이는 당신이 비어 있지 테스트 [.!='']을 마지막으로 템플릿을 변경하면됩니다 제거 할 모든 생각합니다. (나는 어디서 답을 쓸지 모르겠다).

은 내가 가능한 각 속성에 대해 그런 일을 할 수 있다고 생각 :

<xsl:choose> 
    <xsl:when test="@Weekday"> 
     <xsl:value-of select="@Weekday"/> 
     <xsl:text>,</xsl:text> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:text>,</xsl:text> 
    </xsl:otherwise> 
</xsl:choose> 

그래서 존재하는 경우 그것은 단지, 레코드에 값을하지 않을 경우 둘 것이다 ",". 그러나 나는 이것을 이미 XSLT에 삽입하는 방법을 모른다.

attribute = "" 인 경우 작업 하시겠습니까?하지만 테이블 열과 일치하는 가능한 속성 목록이 있기 때문에 속성 존재 여부를 확인해야합니다. XML 입력 파일에는 그들. - klipa 3 시간 전 [이 주석 삭제]

0

출력이 데이터베이스에로드되므로 출력의 열 순서가 중요합니다.

빈 노드 집합의 문자열 값이 빈 문자열이므로 모든 특성이 존재하는지 테스트 할 필요가 없습니다.

출력이 DOCID 및 보안에서 다르게 생성되었으므로 더 깨끗한 스타일을 사용하십시오.

또한 xsl : strip-space를 추가하여 입력 문서의 공백을 무시했습니다.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="text" /> 
    <xsl:strip-space elements="*" /> 

    <xsl:template match="RECORDS"> 
     <xsl:apply-templates select="ancestor::DOCID" mode="print" /> 
     <xsl:apply-templates select="ancestor::FIRM" mode="print" /> 
     <xsl:apply-templates select="ancestor::FIRM/CURRENCY" mode="print" /> 
     <xsl:apply-templates select="ancestor::DEPARTMENT" mode="print" /> 
     <xsl:apply-templates select="ancestor::SETTLEDATE" mode="print" /> 
     <xsl:apply-templates select="ancestor::SECURITY" mode="print" /> 
     <xsl:apply-templates select="ancestor::TRDACC" mode="print" /> 

     <xsl:value-of select="@RecNo" /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="@TradeNo" /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="@TradeTime" /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="@Price" /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="@Quantity" /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="@Value" /> 
     <xsl:text>&#10;&#13;</xsl:text> 

    </xsl:template> 

    <xsl:template match="DOCID" mode="print"> 
     <xsl:value-of select="@TradeDate" /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="@Weekday" /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="@WMainFirmId" /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="@FirmName" /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="@WFirmINN" /> 
     <xsl:text>,</xsl:text> 
    </xsl:template> 

    <xsl:template match="SECURITY" mode="print"> 
     <xsl:value-of select="concat(@SecurityId,',',@SecShortName,',',@SecurityType,',',@FaceValue,',')" /> 
    </xsl:template> 

    <!-- etc for each element we apply in the RECORD template --> 

</xsl:stylesheet> 
+0

답변 해 주셔서 감사합니다. 내가 제안한 스크립트를 실행하려했지만 출력이 나오지 않았습니까? – klipa

+0

@klipa 죄송합니다. 이전에 RECORDS 대신 RECORD를 작성했습니다. –

1

출력을 많이 구동하기 위해 XML 문서의 구조에 의존 스타일 시트의 이전 버전은, 종종 '푸시'방법으로 언급했다.

당신이 속성의 일부있을 것이라는 점을 확실하지 않은 경우에, 당신은 ''더 구체적으로 특정 순서의 특정 속성을 요청하는 스타일 시트를 사용할 수 있습니다

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="/DOC/DOCID/FIRM/CURRENCY/DEPARTMENT/SETTLEDATE/SECURITY/TRDACC"/> 
    </xsl:template> 

<xsl:template match="TRDACC"> 
    <xsl:value-of select="preceding::DOC_REQUISITES/@DOC_DATE"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="preceding::DOC_REQUISITES/@DOC_NO"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::DOCID/@TradeDate"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::DOCID/@Weekday"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::DOCID/@MainFirmId"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::DOCID/@FirmName"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::DOCID/@FirmINN"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::FIRM/@FirmID"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::CURRENCY/@CurrencyId"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::DEPARTMENT/@DepartmentId"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::DEPARTMENT/@DepName"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::SETTLEDATE/@SettleDate"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::SECURITY/@SecurityId"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::SECURITY/@SecShortName"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::SECURITY/@SecurityType"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="ancestor::SECURITY/@FaceValue"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="@TrdAccId"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="RECORDS/@RecNo"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="RECORDS/@TradeNo"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="RECORDS/@TradeTime"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="RECORDS/@Price"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="RECORDS/@Quantity"/> 
    <xsl:text>,</xsl:text> 
    <xsl:value-of select="RECORDS/@Value"/> 
    <xsl:text>&#10;</xsl:text> 

</xsl:template> 

</xsl:stylesheet> 

속성이 없으면 값에 아무 것도 선택하지 않고 쉼표 사이에 빈 자리를 남겨 둡니다.

+0

감사합니다. Mads. 그냥 대답하시오. 나는 사무실에 없으며 나중에 스크립트를 시도 할 것입니다. (가정에서 테스트 환경을 갖지 마십시오.) 그것이 어떻게 작동하는지 알려 드리겠습니다. 다시 한번 감사드립니다. – klipa

관련 문제