Как я могу преобразовать xml в csv через xsltproc, где данные из node1 включены для одной или нескольких записей в node2, введенных на том же уровне

#xml #xslt #xml-parsing

#xml #xslt #xml-синтаксический анализ

Вопрос:

ниже приведен пример моих данных (чтобы легко продемонстрировать иерархию)

client.xml

 <?xml version="1.0" encoding="UTF-8"?>
<ns1:ClientMasterMessage xmlns:ns1="urn:pubcom:0127:PUB_I_PUN_PPM1.0">
    <ClientRecord>
        <GeneralData>
            <ObjectType>C</ObjectType>
            <ClientID>0100777879</ClientID>
            <ClientName>CLIENT_NAME1</ClientName>
            <ClientName2/>
            <ClientStreet>140 WEST 29TH STREET</ClientStreet>
            <ClientState>NY</ClientState>
            <ClientCountry>US</ClientCountry>
            <ClientStatus>02</ClientStatus>
        </GeneralData>
        <OrgaData>
            <CompanyCode>1A6</CompanyCode>
            <AgencyCode>1A62</AgencyCode>
            <SalesOrg>1A6B</SalesOrg>
            <Currency>USD</Currency>
            <JobAccountDir>02###273</JobAccountDir>
            <FinanceControl>02----31</FinanceControl>
        </OrgaData>
        <OrgaData>
            <CompanyCode>1A5</CompanyCode>
            <AgencyCode>1A55</AgencyCode>
            <SalesOrg>1A6A</SalesOrg>
            <Currency>USD</Currency>
            <JobAccountDir>02###650</JobAccountDir>
            <FinanceControl>02----27</FinanceControl>
        </OrgaData>
    </ClientRecord>
    <ClientRecord>
        <GeneralData>
            <ObjectType>C</ObjectType>
            <ClientID>0100061317</ClientID>
            <ClientName>CLIENT2</ClientName>
            <ClientName2/>
            <ClientStreet>4012 14TH STREET</ClientStreet>
            <ClientState>MS</ClientState>
            <ClientCountry>US</ClientCountry>
            <ClientStatus>06</ClientStatus>
        </GeneralData>
        <OrgaData>
            <CompanyCode>1A6</CompanyCode>
            <AgencyCode>1A67</AgencyCode>
            <SalesOrg>1A6C</SalesOrg>
            <Currency>USD</Currency>
            <JobAccountDir>00000000</JobAccountDir>
            <FinanceControl>00000000</FinanceControl>
        </OrgaData>
    </ClientRecord>
</ns1:ClientMasterMessage>
  

Я пытаюсь создать файл .xsl, в который будет записано следующее

 ObjectType|ClientID|ClientName|CompanyCode|AgencyCode
C|0100777879|CLIENT_NAME1|1A6|1A62
C|0100777879|CLIENT_NAME1|1A5|1A55
C|0100061317|CLIEN2|1A6|1A67
  

однако мой файл xsl

 <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="urn:pubcom:0127:PUB_I_PUN_PPM1.0">
<xsl:output method="text"  encoding="UTF-8" />

 <xsl:template match="/ns1:ClientMasterMessage">

    <!-- output the header row -->

      <xsl:text>ObjectType|ClientID|ClientName|CompanyCode|AgencyCodeamp;#13;amp;#10;</xsl:text>
      <xsl:variable name="common">
        <xsl:text>"</xsl:text>
        <xsl:value-of select="ClientRecord/GeneralData/ObjectType"/>
        <xsl:text>"|"</xsl:text>
        <xsl:value-of select="ClientRecord/GeneralData/ClientID"/>
        <xsl:text>"|"</xsl:text>
        <xsl:value-of select="ClientRecord/GeneralData/ClientName"/>
        <xsl:text>"|"</xsl:text>
    </xsl:variable>
    <xsl:for-each select="ClientRecord/OrgaData">
                <xsl:value-of select="$common"/>
        <xsl:value-of select="CompanyCode"/>
        <xsl:text>"|"</xsl:text>
        <xsl:value-of select="AgencyCode"/>
        <xsl:text>"amp;#13;amp;#10;</xsl:text>

   </xsl:for-each>

  <!-- output newline  -->


<!-- chcunk -->
 </xsl:template>
</xsl:stylesheet>
  

производит

 C|0100777879|CLIENT_NAME1|1A6|1A62
C|0100777879|CLIENT_NAME1|1A5|1A55
C|0100777879|CLIENT_NAME1|1A6|1A67
  

другой подход, который я использовал

 <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="urn:pubcom:0127:PUB_I_PUN_PPM1.0">
<xsl:output method="text"  encoding="UTF-8" />

<xsl:template match="/ns1:ClientMasterMessage">
<ns1:ClientMasterMessage>
<xsl:text>OjbectType|ClientID|ClientName|CompanyCode|AgencyCode</xsl:text>
<xsl:text>"amp;#13;amp;#10;</xsl:text>

<xsl:for-each select="ClientRecord">
<ClientRecord>
<ObjectType>
<xsl:value-of   select="./GeneralData/ObjectType"/>
</ObjectType>
<xsl:text>"|"</xsl:text>
<ClientID>
<xsl:value-of   select="./GeneralData/ClientID"/>
</ClientID>
<xsl:text>"|"</xsl:text>
<ClientName>
<xsl:value-of   select="./GeneralData/ClientName"/>
</ClientName>
<xsl:text>"|"</xsl:text>



<xsl:text>"|"</xsl:text>
<CompanyCode>
<xsl:value-of   select="./OrgaData/CompanyCode"/>
</CompanyCode>
<xsl:text>"|"</xsl:text>
<AgencyCode>
<xsl:value-of   select="./OrgaData/AgencyCode"/>
</AgencyCode>
<xsl:text>"amp;#13;amp;#10;</xsl:text>
</ClientRecord>
</xsl:for-each>
</ns1:ClientMasterMessage>
</xsl:template>
</xsl:stylesheet>
  

Создано две строки

 ObjectType|ClientID|ClientName|CompanyCode|AgencyCode
C|0100777879|CLIENT_NAME1|1A5|1A55
C|0100061317|CLIEN2|1A6|1A67
  

Есть ли способ повторить GeneralData для каждой записи OrgaData для данного ClientRecord? Или оператор value-of имеет внутренние ограничения?

Любые предложения о том, как наилучшим образом использовать этот котенок, будут приветствоваться. Результат этого упражнения станет вводом в денормализованную таблицу.

Ответ №1:

Вывод, который вы показываете, может быть получен с помощью:

XSLT 1.0

 <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="urn:pubcom:0127:PUB_I_PUN_PPM1.0">
<xsl:output method="text" encoding="UTF-8" />

<xsl:template match="/ns1:ClientMasterMessage">
    <!-- header row -->
    <xsl:text>ObjectType|ClientID|ClientName|CompanyCode|AgencyCodeamp;#13;amp;#10;</xsl:text>
    <!-- general data -->
    <xsl:for-each select="ClientRecord">
        <xsl:variable name="common">
            <xsl:value-of select="GeneralData/ObjectType"/>
            <xsl:text>|</xsl:text>
            <xsl:value-of select="GeneralData/ClientID"/>
            <xsl:text>|</xsl:text>
            <xsl:value-of select="GeneralData/ClientName"/>
            <xsl:text>|</xsl:text>
        </xsl:variable>
        <!-- output -->
        <xsl:for-each select="OrgaData">
            <xsl:value-of select="$common"/>
            <xsl:value-of select="CompanyCode"/>
            <xsl:text>|</xsl:text>
            <xsl:value-of select="AgencyCode"/>
            <xsl:text>amp;#13;amp;#10;</xsl:text>
       </xsl:for-each>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
  

Комментарии:

1. Большое спасибо за предложение!!! Это сработало. Я был на итерации / попытке 15 и не уверен, сколько еще попыток, прежде чем я наткнулся на правильный подход.