반응형
XSLT를 사용한 XML에서 CSV로
다음과 같은 XML 문서를 가지고 있습니다.
<projects>
<project>
<name>Shockwave</name>
<language>Ruby</language>
<owner>Brian May</owner>
<state>New</state>
<startDate>31/10/2008 0:00:00</startDate>
</project>
<project>
<name>Other</name>
<language>Erlang</language>
<owner>Takashi Miike</owner>
<state> Canceled </state>
<startDate>07/11/2008 0:00:00</startDate>
</project>
...
XSLT(변환) 결과를 통해 다음과 같은 결과를 얻고자 합니다.
Shockwave,Ruby,Brian May,New,31/10/2008 0:00:00
Other,Erlang,Takashi Miike,Cancelled,07/11/2008 0:00:00
이를 달성하기 위한 XSLT를 아는 사람이 있습니까?중요한 경우를 대비해서 .net을 사용하고 있습니다.
다음은 프로그래밍 방식으로 설정할 수 있는 구성 가능한 매개 변수가 포함된 버전입니다.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8" />
<xsl:param name="delim" select="','" />
<xsl:param name="quote" select="'"'" />
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:apply-templates select="projects/project" />
</xsl:template>
<xsl:template match="project">
<xsl:apply-templates />
<xsl:if test="following-sibling::*">
<xsl:value-of select="$break" />
</xsl:if>
</xsl:template>
<xsl:template match="*">
<!-- remove normalize-space() if you want keep white-space at it is -->
<xsl:value-of select="concat($quote, normalize-space(), $quote)" />
<xsl:if test="following-sibling::*">
<xsl:value-of select="$delim" />
</xsl:if>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
여기서 XML 변환 스타일시트를 찾았습니다(웨이백 시스템 링크, 사이트 자체가 독일어).
여기에 추가된 스타일시트가 도움이 될 수 있습니다.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="iso-8859-1"/>
<xsl:strip-space elements="*" />
<xsl:template match="/*/child::*">
<xsl:for-each select="child::*">
<xsl:if test="position() != last()">"<xsl:value-of select="normalize-space(.)"/>", </xsl:if>
<xsl:if test="position() = last()">"<xsl:value-of select="normalize-space(.)"/>"<xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
CSV 파일을 사용할 위치에 따라 xsl:if 태그 내부의 따옴표를 제거하여 값을 따옴표에 넣지 않도록 할 수도 있습니다.
이것.xsl:stylesheet
지정된 열 머리글 목록을 사용할 수 있으며 행이 올바르게 정렬되도록 합니다.XSLT 버전 2.0이 필요합니다.
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:csv="csv:csv">
<xsl:output method="text" encoding="utf-8"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="delimiter" select="','"/>
<csv:columns>
<column>name</column>
<column>sublease</column>
<column>addressBookID</column>
<column>boundAmount</column>
<column>rentalAmount</column>
<column>rentalPeriod</column>
<column>rentalBillingCycle</column>
<column>tenureIncome</column>
<column>tenureBalance</column>
<column>totalIncome</column>
<column>balance</column>
<column>available</column>
</csv:columns>
<xsl:template match="/property-manager/properties">
<!-- Output the CSV header -->
<xsl:for-each select="document('')/*/csv:columns/*">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:value-of select="$delimiter"/>
</xsl:if>
</xsl:for-each>
<xsl:text>
</xsl:text>
<!-- Output rows for each matched property -->
<xsl:apply-templates select="property"/>
</xsl:template>
<xsl:template match="property">
<xsl:variable name="property" select="."/>
<!-- Loop through the columns in order -->
<xsl:for-each select="document('')/*/csv:columns/*">
<!-- Extract the column name and value -->
<xsl:variable name="column" select="."/>
<xsl:variable name="value" select="$property/*[name() = $column]"/>
<!-- Quote the value if required -->
<xsl:choose>
<xsl:when test="contains($value, '"')">
<xsl:variable name="x" select="replace($value, '"', '""')"/>
<xsl:value-of select="concat('"', $x, '"')"/>
</xsl:when>
<xsl:when test="contains($value, $delimiter)">
<xsl:value-of select="concat('"', $value, '"')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
<!-- Add the delimiter unless we are the last expression -->
<xsl:if test="position() != last()">
<xsl:value-of select="$delimiter"/>
</xsl:if>
</xsl:for-each>
<!-- Add a newline at the end of the record -->
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
이것.CsvEscape
함수는 XSLT 1.0이며 열 값을 탈출합니다.,
,"
, 그리고 RFC 4180이나 엑셀 같은 새로운 라인들.XSLT 템플릿을 재귀적으로 호출할 수 있다는 점을 활용합니다.
- 템플릿
EscapeQuotes
는 문자열의 시작부터 재귀적으로 모든 큰따옴표를 2개의 큰따옴표로 바꿉니다. - 템플릿
CsvEscape
텍스트에 쉼표 또는 큰따옴표가 포함되어 있는지 확인하고, 그런 경우 문자열 전체를 큰따옴표와 호출 쌍으로 둘러싸도록 합니다.EscapeQuotes
현에 맞게
사용 예시:xsltproc xmltocsv.xslt file.xml > file.csv
<?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" encoding="UTF-8"/>
<xsl:template name="EscapeQuotes">
<xsl:param name="value"/>
<xsl:choose>
<xsl:when test="contains($value,'"')">
<xsl:value-of select="substring-before($value,'"')"/>
<xsl:text>""</xsl:text>
<xsl:call-template name="EscapeQuotes">
<xsl:with-param name="value" select="substring-after($value,'"')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="CsvEscape">
<xsl:param name="value"/>
<xsl:choose>
<xsl:when test="contains($value,',')">
<xsl:text>"</xsl:text>
<xsl:call-template name="EscapeQuotes">
<xsl:with-param name="value" select="$value"/>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:when test="contains($value,'
')">
<xsl:text>"</xsl:text>
<xsl:call-template name="EscapeQuotes">
<xsl:with-param name="value" select="$value"/>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:when test="contains($value,'"')">
<xsl:text>"</xsl:text>
<xsl:call-template name="EscapeQuotes">
<xsl:with-param name="value" select="$value"/>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<xsl:text>project,name,language,owner,state,startDate</xsl:text>
<xsl:text>
</xsl:text>
<xsl:for-each select="projects/project">
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(name)"/></xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(language)"/></xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(owner)"/></xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(state)"/></xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(startDate)"/></xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
언급URL : https://stackoverflow.com/questions/365312/xml-to-csv-using-xslt
반응형
'programing' 카테고리의 다른 글
Angular에서 선택한 사용 예가 필요합니다.JS입력양식 (0) | 2023.10.05 |
---|---|
MYSql의 새 줄 문자 바꾸기가 작동하지 않습니다. (0) | 2023.10.05 |
MYSQL SELECT 1년 전 기록 (0) | 2023.10.05 |
보기 페이지에서 현재 조각 인스턴스 가져오기 (0) | 2023.10.05 |
쿼리 결과를 mysql에서 10진수로 캐스트 (0) | 2023.10.05 |