2008-12-13 4 views
63

У меня есть следующий XML-документ:XML в CSV Использование XSLT

<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 в случае, если это имеет значение.

Спасибо!

+0

.NET имеет значение, только если вы используете [XslTransform Class] (http://msdn.microsoft.com/en-us/library/system.xml.xsl.xsltransform%28v=vs.110% 29.aspx), который поддерживает только xslt 1.0. Это ограничение? Если это так, его следует пометить в [xslt-1.0] (http://stackoverflow.com/tags/xslt-1.0/info). – 2013-02-06 17:22:15

+0

Хороший ответ также приведен здесь для аналогичного вопроса, если вы используете Linux http://askubuntu.com/questions/174143/convert-xml-to-csv-shell-command-linee – 2017-03-09 10:58:47

+0

Существует инструмент [xml2csv] (https://github.com/fordfrog/xml2csv). Может быть, это тоже полезно в вашем случае? – koppor 2017-07-01 04:35:36

ответ

37

Найден XML преобразование STYLESHEET here (сайт сам по себе является на немецком языке)

Стилевая добавил здесь может быть полезным:

<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>&#xD;</xsl:text> 
</xsl:if> 
</xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 

Может быть, вы хотите, чтобы удалить кавычки внутри XSL: если теги так он не помещает ваши значения в кавычки, в зависимости от того, где вы хотите использовать CSV-файл.

-6

Рассмотрите возможность игнорирования дополнительного слоя (XSLT) и использования вашего языка программирования .NET напрямую.

Прочность XSLT больше в преобразовании одного XML в другой формат XML.

+0

Почему downvotes? – stesch 2008-12-14 01:38:51

+0

@stesch: Я бы искушал себя downvote, но кто-то уже это сделал. :) Мои причины таковы, что на вопрос типа «Как я могу летать от А до Б»? ваш ответ: «Не летайте, не ездите!». Кроме того, как вы знаете, что .NET используется, а обработка XSLT - это «дополнительный уровень»? – 2008-12-14 18:54:58

46

Вот версия с настраиваемыми параметрами, которые можно установить программно:

<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="'&quot;'" /> 
    <xsl:param name="break" select="'&#xA;'" /> 

    <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> 
15

Это 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>&#xa;</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, '&quot;')"> 
        <xsl:variable name="x" select="replace($value, '&quot;', '&quot;&quot;')"/> 
        <xsl:value-of select="concat('&quot;', $x, '&quot;')"/> 
       </xsl:when> 
       <xsl:when test="contains($value, $delimiter)"> 
        <xsl:value-of select="concat('&quot;', $value, '&quot;')"/> 
       </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>&#xa;</xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 
Смежные вопросы