Некоторый форпост результат с использованием двух условий - PullRequest
1 голос
/ 18 февраля 2011

Мне нужно преобразовать XML-файл, в котором я должен проверить идентификатор поля '0', идентификатор поля '1' и идентификатор поля суммы '2'.Например, у меня есть:

<document>
    <line id="0">
        <field id="0">MAR</field>
        <field id="1">doc1</field>
        <field id="2">2</field>
    </line>
    <line id="1">
        <field id="0">MAR</field>
        <field id="1">doc2</field>
        <field id="2">3</field>
    </line>
    <line id="2">
        <field id="0">AAA></field>
        <field id="1">doc4</field>
    </line>
    <line id="3">
        <field id="0">MAR</field>
        <field id="1">doc1</field>
        <field id="2">4</field>
    </line>
</document>

результат должен быть:

<type-MAR>
    <document>doc1</document>
    <sum>6</sum>
    </type-MAR>   
<type-MAR>
    <document>doc2</document>
    <sum>3</sum>
</type-MAR>

там я должен взять все строки MAR и показать некоторые результаты, которые зависят от поля id '1'.

Моя идея состояла в том, чтобы сначала сделать цикл (для каждого) и использовать условие (когда).Может быть, кто-то предложит более оптимистичное решение.

Я добавляю новую заметку, как проверить, поступают ли данные так:

<field id="0">MAR999</field>
<field id="1">doc1-1231</field>

Первое поле, в котором я пытаюсь использовать функцию, содержит 'MAR', другие подстроки-до '-'.но я застрял, когда я пытаюсь использовать его в вашей программе.может быть, вы можете посоветоваться с ним?

Ответы [ 4 ]

2 голосов
/ 18 февраля 2011
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:key name="kLine" match="line" use="field[@id='1']"/>
    <xsl:template match="/*">
        <r>
            <xsl:apply-templates select="line
                [field[@id='0'] = 'MAR']
                [count(
                    . | key('kLine', field[@id='1'])[1]
                    ) = 1]
                "/>
        </r>
    </xsl:template>
    <xsl:template match="line">
        <type-MAR>
            <document>
                <xsl:value-of select="field[@id='1']"/>
            </document>
            <sum>
                <xsl:value-of select="
                    sum(
                        key('kLine', field[@id='1'])/
                        field[@id='2']
                        )"/>
            </sum>
        </type-MAR>
    </xsl:template>
</xsl:stylesheet>

Корректно по вашему образцу будет:

<r>
    <type-MAR>
        <document>doc1</document>
        <sum>6</sum>
    </type-MAR>
    <type-MAR>
        <document>doc2</document>
        <sum>3</sum>
    </type-MAR>
</r>
2 голосов
/ 18 февраля 2011

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kLineById0-Id1" match="line"
             use="concat(field[@id='0'],'+',field[@id='1'])"/>
    <xsl:param name="pId0" select="'MAR'"/>
    <xsl:template match="document">
        <result>
            <xsl:apply-templates select="line[generate-id()=
                                              generate-id(
                                                 key('kLineById0-Id1',
                                                     concat($pId0,
                                                            '+',
                                                            field[@id='1']
                                                     )
                                                 )[1]
                                              )]"/>
        </result>
    </xsl:template>
    <xsl:template match="line">
        <xsl:element name="type-{$pId0}">
            <document>
                <xsl:value-of select="field[@id='1']"/>
            </document>
            <sum>
                <xsl:value-of select="sum(key('kLineById0-Id1',
                                              concat(field[@id='0'],
                                                     '+',
                                                     field[@id='1']
                                              )
                                          )/field[@id='2']
                                      )"/>
            </sum>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<result>
    <type-MAR>
        <document>doc1</document>
        <sum>6</sum>
    </type-MAR>
    <type-MAR>
        <document>doc2</document>
        <sum>3</sum>
    </type-MAR>
</result>

Примечание : группировка по обоим @id атрибутам, группе сумм, имени динамического элемента, параметризацияпервый @ id.

2 голосов
/ 18 февраля 2011

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kLineById0Id1" match="line[field[@id=2]]"
  use="concat(field[@id=0],'+',field[@id=1])"/>

 <xsl:template match=
  "line[field[@id=2]
      and
        generate-id()
       =
        generate-id(key('kLineById0Id1',
                        concat(field[@id=0],
                               '+',field[@id=1])
                       )[1])
       ]
  ">
  <xsl:element name="type-{field[@id=0]}">
       <document>
        <xsl:value-of select="field[@id=1]"/>
       </document>
       <sum>
        <xsl:value-of select=
        "sum(key('kLineById0Id1',
                concat(field[@id=0],
                       '+',field[@id=1])
               )
               /field[@id=2]
           )
        "/>
       </sum>
     </xsl:element>
 </xsl:template>

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

при применении к предоставленному документу XML:

<document>
    <line id="0">
        <field id="0">MAR</field>
        <field id="1">doc1</field>
        <field id="2">2</field>
    </line>
    <line id="1">
        <field id="0">MAR</field>
        <field id="1">doc2</field>
        <field id="2">3</field>
    </line>
    <line id="2">
        <field id="0">AAA></field>
        <field id="1">doc4</field>
    </line>
    <line id="3">
        <field id="0">MAR</field>
        <field id="1">doc1</field>
        <field id="2">4</field>
    </line>
</document>

дает желаемый, правильный результат:

<type-MAR>
   <document>doc1</document>
   <sum>6</sum>
</type-MAR>
<type-MAR>
   <document>doc2</document>
   <sum>3</sum>
</type-MAR>

Пояснение : * Метод Muenchian для группировки используется с ключом, определенным как объединение двух элементов.

0 голосов
/ 21 февраля 2011

Спасибо за ответы, я использую решение Флэка и исправляю:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:key name="kLine" match="line" use="substring(field[@id='1'],1,4)"/>
    <xsl:template match="/*">
        <document>
            <xsl:apply-templates select="line[contains(field[@id='0'], 'MAR')][count(. | key('kLine', substring(field[@id='1'],1,4))[1]) = 1]"/>
        </document>
    </xsl:template>
    <xsl:template match="line">
        <type-MAR>
            <document>
                <xsl:value-of select="substring(field[@id='1'],1,4)"/>
            </document>
            <sum>
                <xsl:value-of select="sum(key('kLine', substring(field[@id='1'],1,4))/field[@id='2'])"/>
            </sum>
        </type-MAR>
    </xsl:template>
</xsl:stylesheet>

Решения Димитра и Алехандро также хороши и полезны (возможно, более профессиональны).Но Димитр больше концентрируется на моей задаче, которую я написал, например, он использует условие, чтобы проверить, есть ли у нас второе поле (я не писал, что не только у MAR может быть field2).Алехандро, чтобы проверить его использование параметра, поэтому для меня это был хороший урок, чтобы найти больше информации, как его использовать, потому что с языком xsl у меня есть опыт менее одного месяца.Поэтому мне было сложно подготовить Ваши программы для моей работы.Flack текст был более понятным для меня, как для начинающего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...