2010-12-13 3 views
1

Я надеюсь получить помощь здесь еще раз. Вот мой пример входного XML:XSLT: Как преобразовать XML в текстовый файл с Muenchian Grouping

<Report> 
    <RecordValues> 
    <Record> 
     <FieldValue fieldName="firm_name" fieldValue="Firm_1"/> 
     <FieldValue fieldName="firm_number" fieldValue="11"/> 
     <FieldValue fieldName="prepared_by" fieldValue="PARKER"/> 
     <FieldValue fieldName="contact_number" fieldValue="123456789"/> 
     <FieldValue fieldName="trade_date" fieldValue="2010-10-17"/> 
     <FieldValue fieldName="symbol" fieldValue="ADM"/> 
    </Record> 
    <Record> 
    <FieldValue fieldName="firm_name" fieldValue="Firm_1"/> 
     <FieldValue fieldName="firm_number" fieldValue="11"/> 
     <FieldValue fieldName="prepared_by" fieldValue="PARKER"/> 
     <FieldValue fieldName="contact_number" fieldValue="123456789"/> 
     <FieldValue fieldName="trade_date" fieldValue="2010-10-16"/> 
     <FieldValue fieldName="symbol" fieldValue="ACW"/> 
    </Record> 
    <Record> 
     <FieldValue fieldName="firm_name" fieldValue="Firm_2"/> 
     <FieldValue fieldName="firm_number" fieldValue="12"/> 
     <FieldValue fieldName="prepared_by" fieldValue="EDWARDS"/> 
     <FieldValue fieldName="contact_number" fieldValue="123456780"/> 
     <FieldValue fieldName="trade_date" fieldValue="2010-10-19"/> 
     <FieldValue fieldName="symbol" fieldValue="ADS"/> 
    </Record> 
    </RecordValues> 
</Report> 

Вот выход мне нужно получить:

A Firm_1 11 
B PARKER 123456789 
C 2010-10-17 ADM 
C 2010-10-16 ACW 
T 4 
A Firm_2 12 
B EDWARDS 123456780 
C 2010-10-19 ADS 
T 3 

Как вы можете видеть, что нужно сгруппировать записи по «firm_name» или «firm_number». Каждая группа должна иметь одну запись типа «А», одну запись типа «В» и несколько записей типа «С». Запись «T» - это общая сумма каждой группы без записи «T». Входной XML уже отсортирован. Я нашел Muenchian Method, который группирует записи, но ничего не получилось. Очевидно, я делаю что-то неправильно. Вот XSLT Я написал:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="value-by-firm" match="Report/RecordValues/Record/FieldValue" use="firm_number"/> 
    <xsl:template match="Record"> 
    <xsl:for-each select="FieldValue/@fieldValue[count(. | key('value-by-firm', firm_number))]"> 
    <xsl:text>A </xsl:text> 
    <xsl:value-of select="firm_name"/> 
    <xsl:text> </xsl:text> 
    <xsl:value-of select="firm_number"/> 
    <xsl:text>&#xA;</xsl:text> 
    <xsl:text>B </xsl:text> 
    <xsl:value-of select="prepared_by"/> 
    <xsl:text> </xsl:text> 
    <xsl:value-of select="contact_number"/> 
    <xsl:text>&#xA;</xsl:text> 
    <xsl:for-each select="key('value-by-firm', firm_number)"> 
     <xsl:text>C </xsl:text> 
     <xsl:value-of select="trade_date"/> 
     <xsl:text> </xsl:text> 
     <xsl:value-of select="symbol"/> 
     <xsl:text>&#xA;</xsl:text> 
    </xsl:for-each> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

Возможно, есть и другой способ сделать это. Заранее спасибо.

+0

Это не делает * любой * смысл! Что такое «запись типа A», «запись типа B», «запись типа C», «запись типа T»? Какие значения суммируются? –

+0

@Dimitre Novatchev: Это просто жесткий идентификатор записи. – klipa

+0

Общее количество должно показывать количество записей для одной фирмы без самой суммы. – klipa

ответ

1

Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:key name="kRecordByFirmAndContact" match="Record" 
      use="concat(FieldValue[@fieldName='firm_number'] 
          /@fieldValue, 
         '+', 
         FieldValue[@fieldName='contact_number'] 
          /@fieldValue)"/> 
    <xsl:template 
     match="Record 
        [count(.|key('kRecordByFirmAndContact', 
           concat(FieldValue 
              [@fieldName='firm_number'] 
              /@fieldValue, 
             '+', 
             FieldValue 
              [@fieldName='contact_number'] 
              /@fieldValue))[1]) 
        = 1 ]"> 
     <xsl:variable name="vRecords" 
         select="key('kRecordByFirmAndContact', 
            concat(FieldValue 
              [@fieldName='firm_number'] 
              /@fieldValue, 
             '+', 
             FieldValue 
              [@fieldName='contact_number'] 
              /@fieldValue))"/> 
     <xsl:value-of select="concat('A ', 
            *[@fieldName='firm_name'] 
             /@fieldValue, 
            ' ', 
            *[@fieldName='firm_number'] 
             /@fieldValue, 
            '&#xA;', 
            'B ', 
            *[@fieldName='prepared_by'] 
             /@fieldValue, 
            ' ', 
            *[@fieldName='contact_number'] 
             /@fieldValue, 
            '&#xA;')"/> 
     <xsl:apply-templates select="$vRecords" mode="RecordC"/> 
     <xsl:value-of select="concat('T ',count($vRecords) + 2,'&#xA;')"/> 
    </xsl:template> 
    <xsl:template match="Record" mode="RecordC"> 
     <xsl:value-of select="concat('C ', 
            *[@fieldName='trade_date'] 
             /@fieldValue, 
            ' ', 
            *[@fieldName='symbol'] 
             /@fieldValue, 
            '&#xA;')"/> 
    </xsl:template> 
</xsl:stylesheet> 

Выход:

A Firm_1 11 
B PARKER 123456789 
C 2010-10-17 ADM 
C 2010-10-16 ACW 
T 4 
A Firm_2 12 
B EDWARDS 123456780 
C 2010-10-19 ADS 
T 3 

Примечание: Как вы можете видеть, что это не сложно, но ваша схема делает код так многословен ... Это выглядит как M $ XML-формат для дампов данных.

+0

@Alejandro: Большое спасибо за решение. единственное, что я не понял, почему вы конкатентируете «firm_number» и «contact_number»? – klipa

+0

@klipa: Потому что это ключ, вы группируетесь фирмой и человеком, который «подготовил» ее, и похоже, что контактный номер уникален для такого человека. – 2010-12-13 21:16:51

+0

Алехандро: Спасибо. – klipa

1

Вы группируете «неправильную» вещь и неправильно используете группы.

  • Вы пытаетесь сгруппировать Record элементов. Ergo, они должны соответствовать вашему xsl:key (атрибут use=... должен ссылаться на фирменное наименование)
  • Сгруппировочный трюк работает, обрабатывая каждую группу только один раз. Вы не можете явно обрабатывать каждый ключ в xsl:key, поэтому вместо этого вы обрабатываете все значения и просто игнорируете все, кроме , значение в группе - и выполняйте всю обработку этой группы. Это означает, что ваш foreach должен выбрать те же элементы, что и xsl:key, и добавить тест узла ala [count(. | reference-to-group[1]) = 1] - и здесь вы забыли часть [1] и = 1.

Файл неподвижная XSLT затем (обратите внимание, что поиск поле также слегка изменилось, и я не добавлял T вычисления:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="value-by-firm" match="/Report/RecordValues/Record" use="FieldValue[@fieldName='firm_number']/@fieldValue"/> 
    <xsl:template match="/"> 
    <xsl:for-each select="/Report/RecordValues/Record[count(. | key('value-by-firm', FieldValue[@fieldName='firm_number']/@fieldValue)[1]) = 1]"> 
     <xsl:text>A </xsl:text> 
     <xsl:value-of select="FieldValue[@fieldName='firm_name']/@fieldValue"/> 
     <xsl:text> </xsl:text> 
     <xsl:value-of select="FieldValue[@fieldName='firm_number']/@fieldValue"/> 
     <xsl:text>&#xA;</xsl:text> 
     <xsl:text>B </xsl:text> 
     <xsl:value-of select="FieldValue[@fieldName='prepared_by']/@fieldValue"/> 
     <xsl:text> </xsl:text> 
     <xsl:value-of select="FieldValue[@fieldName='contact_number']/@fieldValue"/> 
     <xsl:text>&#xA;</xsl:text> 
     <xsl:for-each select="key('value-by-firm', FieldValue[@fieldName='firm_number']/@fieldValue)"> 
     <xsl:text>C </xsl:text> 
     <xsl:value-of select="FieldValue[@fieldName='trade_date']/@fieldValue"/> 
     <xsl:text> </xsl:text> 
     <xsl:value-of select="FieldValue[@fieldName='symbol']/@fieldValue"/> 
     <xsl:text>&#xA;</xsl:text> 
     </xsl:for-each> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

Изменить: Конечная нота: Что вы делаете с учетом этого схема данных не является одной из сильных сторон XSLT. Похоже, что у вас есть структура данных, которая, естественно, может перевести на более чистую схему (например, в которой пары имя-значение представлены физическими парами имени-значения XML, а именно атрибутами). В качестве альтернативы, вы можете импортировать его в «настоящий» язык программирования (откуда почти наверняка поступают эти данные), где все трещины, такие как FieldValue e lement и атрибуты fieldName и fieldValue не представлены. В основном; хотя это возможно с XML + XSLT, вы получите более сложное, хрупкое решение, чем если бы вы представляли его с более естественным представлением и обрабатывали его с помощью более естественного инструмента.

+0

Благодарим вас за ответ. Знания XSLT очень ограничены. Не могли бы вы привести мне пример. Благодарю. – klipa

+0

Ничего себе, это было очень быстро. Большое спасибо. Может быть, вы также можете мне помочь с учетными записями? – klipa

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