2016-01-12 4 views
0

Мне нужен XML, преобразованный в csv. Это было сложно по двум причинам: 1) Есть несколько дочерних элементов Support_Order_Detail, и для каждого ребенка требуется отдельная строка. 2) Во второй записи нет дочерних элементов Support_Order_Detail. Я использовал сопоставление предшествующего собора на Support_Order_Detail и использовал функцию not [] для обработки записи без узла Support_Order_Detail. Я включил XSLT, с которым я боролся, и он работает. Я получаю правильный вывод. Тем не менее, я знаю, что есть лучший путь, и я получаю ошибку в моем отладчике:XML to CSV: строки печати для каждого дочернего узла и иногда дочернего узла отсутствуют

Неоднозначный матч правила/Report_Data/Report_Entry [2] Похожее как «Report_Data/Report_Entry [нет (Support_Order_Detail)]» и «Report_Data/Report_Entry»

Я надеюсь узнать, может ли кто-нибудь указать, где бы у меня не было дублированного кода, то есть двух шаблонов. Я хотел бы избавиться от функции, использующей функцию not [].

Doe,Jane,Child Support,Mandatory,12345 
Doe,Jane,Child Support,Mandatory,12345 
Dole,Bob,Student Loan,Federal,56789 

.

<Report_Data> 
     <Report_Entry> 
      <Worker> 
       <Last_Name>Doe</Last_Name> 
       <First_Name>Jane</First_Name> 
      </Worker> 
      <Lien_Type>Support Order</Lien_Type> 
      <Lien_Sub_Type>Mandatory</Lien_Sub_Type> 
      <Support_Order_Detail> 
       <Support_Type Descriptor="Current Child Support"> 
        <ID type="Support_Type">CS</ID> 
       </Support_Type> 
      </Support_Order_Detail> 
      <Support_Order_Detail> 
       <Support_Type Descriptor="Past Due Child Support"> 
        <ID type="Support_Type">PDCS</ID> 
       </Support_Type> 
      </Support_Order_Detail> 
      <Case_ID>12345</Case_ID> 
     </Report_Entry> 
     <Report_Entry> 
      <Worker> 
       <Last_Name>Dole</Last_Name> 
       <First_Name>Bob</First_Name> 
      </Worker> 
      <Lien_Type>Student Loan</Lien_Type> 
      <Lien_Sub_Type>Federal</Lien_Sub_Type> 
      <Case_ID>56789</wd:Case_ID> 
     </Report_Entry> 
    </Report_Data> 

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    xmlns:xtt="urn:com.workday/xtt" 
    version="2.0"> 


    <xsl:template match="/"> 
     <File xtt:separator="&#xd;&#xa;"> 
      <xtt:class xtt:name="dateformat" xtt:dateFormat="dd/MM/yyyy"/> 
      <xsl:apply-templates/> 
     </File> 
    </xsl:template> 

    <xsl:template match="Report_Data/Report_Entry"> 
     <xsl:apply-templates select="Support_Order_Detail"/> 
    </xsl:template> 


    <xsl:template match="Support_Order_Detail" > 
     <Record xtt:separator=","> 
      <LastName xtt:maxLength="14"><xsl:value-of select="preceding-sibling::Worker/Last_Name[1]"/></LastName> 
      <FirstName xtt:maxLength="17"><xsl:value-of select="preceding-sibling::Worker/First_Name[1]"/></FirstName> 
      <LienType> 
      <xsl:choose> 
       <xsl:when test="preceding-sibling::Lien_Type[1] = 'Support Order' and Support_Type/@Descriptor = 'Current Child Support'"> 
        <xsl:text>Child Support</xsl:text> 
       </xsl:when> 
       <xsl:when test="preceding-sibling::Lien_Type[1] = 'Support Order' and Support_Type/@Descriptor = 'Past Due Child Support'"> 
        <xsl:text>Child Support</xsl:text> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="Support_Type/@Descriptor"/> 
       </xsl:otherwise> 
      </xsl:choose> 
      </LienType> 
      <LienSubType><xsl:value-of select="preceding-sibling::Lien_Sub_Type[1]"/></LienSubType> 
      <CaseID xtt:maxLength="20"><xsl:value-of select="following-sibling::Case_ID"/></CaseID> 
     </Record> 
    </xsl:template> 

    <xsl:template match="Report_Data/Report_Entry[not(Support_Order_Detail)]" > 
     <Record xtt:separator=","> 
      <LastName xtt:maxLength="14"><xsl:value-of select="Worker/Last_Name"/></LastName> 
      <FirstName xtt:maxLength="17"><xsl:value-of select="Worker/First_Name"/></FirstName> 
      <LienType><xsl:value-of select="Lien_Type"/></LienType> 
      <LienSubType><xsl:value-of select="Lien_Sub_Type"/></LienSubType> 
      <CaseID xtt:maxLength="20"><xsl:value-of select="Case_ID"/></CaseID> 
     </Record> 
    </xsl:template> 

</xsl:stylesheet> 

Ожидаемые результаты XML:

<Record xtt:separator=","> 
     <LastName xtt:maxLength="14">Doe</LastName> 
     <FirstName xtt:maxLength="17">Jane</FirstName> 
     <LienType>Child Support</LienType> 
     <LienSubType>Mandatory</LienSubType> 
     <CaseID xtt:maxLength="20">12345</CaseID> 
    </Record> 
    <Record xtt:separator=","> 
     <LastName xtt:maxLength="14">Doe</LastName> 
     <FirstName xtt:maxLength="17">Jane</FirstName> 
     <LienType>Child Support</LienType> 
     <LienSubType>Mandatory</LienSubType> 
     <CaseID xtt:maxLength="20">12345</CaseID> 
    </Record> 
    <Record xtt:separator=","> 
     <LastName xtt:maxLength="14">Dole</LastName> 
     <FirstName xtt:maxLength="17">Bob</FirstName> 
     <LienType>Student Loan</LienType> 
     <LienSubType>Federal</LienSubType> 
     <CaseID xtt:maxLength="20">56789</CaseID> 
    </Record> 
+1

Это сбивает с толку, потому что (1) ваша таблица стилей ** не ** генерирует CSV и (2) ссылается на узлы, которые не существуют в вашем XML, например. 'CF_ADP_Site_ID'. –

+0

@ michael.hor257k Расширение рабочего дня xtt (XML to text) превратит полученный XML в csv при обработке в приложении Workday. Вы правы, хотя прямые результаты XSLT выше создадут новый XML-документ, чтобы позволить xtt преобразовываться в текст. Линии CF_ADP_Site_ID не должны быть включены. Я поймал еще одну ошибку. Я также забыл включить последнюю строку в первый шаблон: и в последнем: Lengel

+0

Поскольку вы спрашиваете о XSLT, я предлагаю вам опубликовать результат XML, который вы ожидаете получить в результате преобразования XSL. - P.S. Пожалуйста, не публикуйте код в комментариях - вместо этого отредактируйте свой вопрос. –

ответ

0

Так что я не знаю, о какой-либо расширения или инструмента, который вы используете, но делать это в чистом XSLT является довольно простой; сопрягать все Report_Entry элементов, и если у них есть какие-либо петли Support_Order_Detail элементов через все из них, кроме одного last() (потому что мы уже произвели линию для этого):

(я слегка модифицирован, чтобы это использовать переменное вместо дублирующих выбирает)

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="text" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> 

    <xsl:template match="//Report_Entry"> 
     <xsl:variable name="row"> 
      <xsl:value-of select="Worker/Last_Name" />,<xsl:value-of select="Worker/First_Name" />,<xsl:value-of select="Lien_Type"/><xsl:value-of select="Lien_Sub_Type"/>,<xsl:value-of select="Case_ID"/> 
      <xsl:text>&#13;</xsl:text> 
     </xsl:variable> 

     <xsl:value-of select="$row" /> 

     <xsl:for-each select="Support_Order_Detail[position() != last()]">    
      <xsl:value-of select="$row" /> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="text()"/> 


</xsl:transform> 

http://xsltransform.net/bFN1y9B/1

0

Я получаю ошибку в моем отладчика:

Неоднозначный матч правило/Report_Data/Report_Entry [2] Соответствует как "Report_Data/Report_Entry [нет (Support_Order_Detail)]" и "Report_Data/Report_Entry"

ошибка может быть устранена, если вы меняете:

<xsl:template match="Report_Data/Report_Entry"> 

к:

<xsl:template match="Report_Entry"> 

Аналогично, вы можете заменить:

<xsl:template match="Report_Data/Report_Entry[not(Support_Order_Detail)]" > 

с:

<xsl:template match="Report_Entry[not(Support_Order_Detail)]" > 

Шаблон матч не выбрать выражение: он не должен включать в себя путь, если образец не является неоднозначным без него (например, если у вас есть Report_Entry в разных местах или на разных уровнях, и вам нужно относиться к ним по-разному.


Что касается «лучшего» кода для достижения того же результата, это в значительной степени зависит от личных предпочтений. ИМХО, если у вас есть два типа Report_Entry, и каждый из них нужно обрабатывать по-разному, при этом отдельный шаблон для их обработки является наилучшим подходом, если разница не минимальна (не ваш случай).

Я бы рассмотрел упрощение блока xsl:choose.

+0

Спасибо, @ micheal.hor257k! Я ценю ваше мнение о наличии двух шаблонов. Мне легче мысленно разобрать два шаблона. Но я ценю решение @Dan Field. Это чище - нет дублирования. Код, который у меня есть, даже сложнее, чем то, что я написал (конечно), но подвел итог тому, что я пытаюсь выполнить. Я, как вы предположили, упростил мое заявление. Еще раз спасибо! – Lengel

+0

Это удалило мою ошибку отладки. Благодаря! – Lengel

+0

@Lengel Если на ваш вопрос ответили, пожалуйста, закройте его, приняв ответ. –

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