2013-09-26 2 views
0

У меня есть XML-файл в этой структуре (см. Ниже), и мне нужно генерировать вывод csv из того же самого.Создать CSV-выход с использованием XSL

<Root> 
    <Metadata> 
    <id>A001</id> 
    <name>Test</name> 
    </Metadata> 
    <Employers> 
    <Employer id="111"> 
     <Employee id="aaa"><Name>Rick</Name></Employee> 
     <Employee id="bbb"><Name>Ram</Name></Employee> 
    </Employer> 
    <Employer id="222"> 
     <Employee id="ddd"><Name>Bob</Name></Employee> 
     <Employee id="dcc"><Name>Tan</Name></Employee> 
    </Employer> 
    </Employers> 
</Root> 

Использование XSL Мне нужно, чтобы генерировать выходной CSV, как показано ниже:

A001, Test, 111, aaa, Rick 
A001, Test, 111, bbb, Ram 
A001, Test, 222, ddd, Bob 
A001, Test, 222, dcc, Tan 

Может кто-нибудь пожалуйста, скажите мне, как генерировать это? FYI, я могу генерировать элементы данных Employer, но не смог генерировать метаданные элементов для каждого & каждой строки Работодателя.

+0

Ожидаете ли вы следовать «Работодателям» с помощью других «Метаданных» и еще более «Работодателей»? –

+0

Сначала мне нужны элементы метаданных (т. Е. Для каждой строки), а затем данные Работодателя. – user972255

+1

Я понимаю это. Мой вопрос заключается в том, что у вас есть * два или более элемента '' Метаданные '' в вашем входном XML, с отдельными «работодателями» после каждого из них? И вам нужен XSLT 1.0 или XSLT 2.0? –

ответ

2

Рецензия на решение для вас, которое следует за RFC4180. Дополнительного места, которое у вас есть после запятой, не должно быть.

данные:

T:\ftemp>type emp2csv.xml 
<Root> 
    <Metadata> 
    <id>A001</id> 
    <name>Test</name> 
    </Metadata> 
    <Employers> 
    <Employer id="111"> 
     <Employee id="aaa"><Name>Rick</Name></Employee> 
     <Employee id="bbb"><Name>Ram</Name></Employee> 
    </Employer> 
    <Employer id="222"> 
     <Employee id="ddd"><Name>Bob</Name></Employee> 
     <Employee id="dcc"><Name>Tan</Name></Employee> 
    </Employer> 
    </Employers> 
</Root> 

Исполнение:

T:\ftemp>call xslt emp2csv.xml emp2csv.xsl 
A001,Test,111,aaa,Rick 
A001,Test,111,bbb,Ram 
A001,Test,222,ddd,Bob 
A001,Test,222,dcc,Tan 

стилевой:

T:\ftemp>type emp2csv.xsl 
<?xml version="1.0" encoding="US-ASCII"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       version="1.0"> 

<xsl:output method="text"/> 

<xsl:variable name="commonFields" 
       select="/*/Metadata/id | /*/Metadata/name"/> 

<xsl:template match="/"> 
    <xsl:apply-templates select="Root/Employers/Employer/Employee"/> 
</xsl:template> 

<!--these elements are CSV fields--> 
<xsl:template match="Employee"> 
    <xsl:for-each select="$commonFields | ../@id | @id | Name"> 
    <xsl:call-template name="doThisField"/> 
    <xsl:if test="position() != last()">,</xsl:if> 
    </xsl:for-each> 
    <xsl:text>&#xa;</xsl:text> 
</xsl:template> 

<!--put out a field escaping content--> 
<xsl:template name="doThisField"> 
    <!--field value escaped per RFC4180--> 
    <xsl:choose> 
    <xsl:when test="contains(.,'&#x22;') or 
        contains(.,',') or 
        contains(.,'&#xa;')"> 
     <xsl:text>"</xsl:text> 
     <xsl:call-template name="escapeQuote"/> 
     <xsl:text>"</xsl:text> 
    </xsl:when> 
    <xsl:otherwise><xsl:value-of select="."/></xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<!--escape a double quote in the current node value with two double quotes--> 
<xsl:template name="escapeQuote"> 
    <xsl:param name="rest" select="."/> 
    <xsl:choose> 
    <xsl:when test="contains($rest,'&#x22;')"> 
     <xsl:value-of select="substring-before($rest,'&#x22;')"/> 
     <xsl:text>""</xsl:text> 
     <xsl:call-template name="escapeQuote"> 
     <xsl:with-param name="rest" select="substring-after($rest,'&#x22;')"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="$rest"/> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 

Edited удалить лишние правила шаблона.

+0

Отлично! Большое спасибо за то, что помогли мне. – user972255

+0

Хорошее решение - я бы не подумал, что в моем одиночку будет побег. – JohnLBevan

1
<?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"/> 
    <xsl:template match="/Root"> 
    <xsl:apply-templates select="Employers/Employer/Employee" /> 
    </xsl:template> 
    <xsl:template match="/Root/Employers/Employer/Employee"> 
    <xsl:value-of select="../../../Metadata/id"/> 
    <xsl:call-template name="delim" /> 
    <xsl:value-of select="../../../Metadata/name"/> 
    <xsl:call-template name="delim" /> 
    <xsl:value-of select="../@id"/> 
    <xsl:call-template name="delim" /> 
    <xsl:value-of select="@id"/> 
    <xsl:call-template name="delim" /> 
    <xsl:value-of select="./Name"/> 
    <xsl:call-template name="linebreak" /> 
    </xsl:template> 
    <xsl:template name="delim"> 
    <xsl:text>, </xsl:text> 
    </xsl:template> 
    <xsl:template name="linebreak"> 
    <xsl:text>&#xA;</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 

Использование <xsl:text>&#xD;&#xA;</xsl:text> (возврат каретки + перевод строки) вместо <xsl:text>&#xA;</xsl:text> (строк), если вы хотите окончания линии окна стилей (например, эквивалентны \n против \r\n в большинстве языков).

NB: Разделитель и разрыв строки находятся в их собственных шаблонах, чтобы облегчить вам изменение символов без обновления в нескольких местах/необходимости копаться в шаблоне, использующем для совместного использования данных.

+0

По какой-то причине это не работает для меня. – user972255

+0

Что происходит, когда вы пытаетесь? Какой движок XSL вы используете (FYI: я написал/протестировал в Visual Studio 2010, а также протестировал здесь: http://www.xslfiddle.net/). Я исправил, чтобы удалить несколько MS-бит выше, если это поможет. , , – JohnLBevan

+0

пс. Раньше я бы вносил поправки в XML в ваш вопрос, так как отсутствовал конечный тег для элемента employee - если это также неверно в исходном XML, что может быть причиной проблемы; Я предполагал, что это была опечатка, когда вы отправляли вопрос, поэтому не подумал выделить его раньше. – JohnLBevan

Смежные вопросы