XML в CSV с помощью XSLT
у меня есть следующий 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 в случае, если это имеет значение.
спасибо!
4 ответа:
найдена таблица стилей преобразования 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>
возможно, вы хотите удалить кавычки внутри xsl:если теги так не помещают ваши значения в кавычки, в зависимости от того, где вы хотите использовать CSV-файл.
вот версия с настраиваемыми параметрами, которые можно задать программно:
<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>
этой
xsl:stylesheet
можно использовать указанный список заголовков столбцов и будет гарантировать, что строки будут правильно упорядочены.<?xml version="1.0"?> <xsl:stylesheet version="1.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>