счетчик с определенным условием - PullRequest
0 голосов
/ 21 мая 2019

У меня проблема с условным приращением для ввода ниже.

условие: В моем ожидаемом вводе 5 будет повторяться.Я хочу добавить версионность к элементу, если он повторяется и только если он имеет значение, равное 5

Вход

<?xml version="1.0"?><?xml-stylesheet type="text/xsl"?> <data> <rec>
    <Pt>1</Pt>
  </rec>
  <rec>
    <Pt>3</Pt>
  </rec>
  <rec>
    <Pt>5</Pt>
  </rec>
  <rec>
    <Pt>5</Pt>
  </rec>
  <rec>
    <Pt>5</Pt>
  </rec>
  <rec>
    <Pt>6</Pt>
  </rec>
</data>

Ожидаемый вывод:

<?xml version="1.0" encoding="UTF-8"?>
<Record>
    <PT>1</PT>
    <DerivedPT>1</DerivedPT>
</Record>
<Record>
    <PT>3</PT>
    <DerivedPT>3</DerivedPT>
</Record>
<Record>
    <PT>5</PT>
    <DerivedPT>5.1</DerivedPT>
</Record>
<Record>
    <PT>5</PT>
    <DerivedPT>5.2</DerivedPT>
</Record>
<Record>
    <PT>5</PT>
    <DerivedPT>5.3</DerivedPT>
</Record>
<Record>
    <PT>6</PT>
    <DerivedPT>6</DerivedPT>
</Record>

У меня естьпробовал это XSLT:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:template match="/">
        <xsl:for-each select="data/rec">
            <Record>
                <PT>
                    <xsl:value-of select="Pt" />
                </PT>
                <DerivedPT>
                    <xsl:variable name="pt" select="Pt" />
                    <xsl:choose>
                        <xsl:when test="contains($pt,'5')">
                            <xsl:value-of
                                select="concat($pt,'.',count(preceding-sibling::rec/Pt[1])+1)" />
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="$pt" />
                        </xsl:otherwise>
                    </xsl:choose>
                </DerivedPT>
            </Record>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>    

Но вывод, который я получаю:

<?xml version="1.0" encoding="UTF-8"?>
<Record>
    <PT>1</PT>
    <DerivedPT>1</DerivedPT>
</Record>
<Record>
    <PT>3</PT>
    <DerivedPT>3</DerivedPT>
</Record>
<Record>
    <PT>5</PT>
    <DerivedPT>5.3</DerivedPT>
</Record>
<Record>
    <PT>5</PT>
    <DerivedPT>5.4</DerivedPT>
</Record>
<Record>
    <PT>5</PT>
    <DerivedPT>5.5</DerivedPT>
</Record>
<Record>
    <PT>6</PT>
    <DerivedPT>6</DerivedPT>
</Record>

Это потому, что он выбирает все теги. Какие изменения мне нужно сделать, так что потребуетсятолько PT, который равен 5.

                        <xsl:value-of
                            select="concat($pt,'.',count(preceding-sibling::rec/Pt[1])+1)" />

Ответы [ 3 ]

1 голос
/ 21 мая 2019

Хотя повторение может быть только 5, это может быть возможностью использовать технику, называемую мюнхенская группировка , поскольку это хороший метод обучения (при условии, что вы ограничены XSLT 1.0)

В этом случае вы можете переписать свой XSLT следующим образом ...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes" />

  <xsl:key name="recs" match="rec" use="Pt" />

  <xsl:template match="data">
    <xsl:copy>
      <xsl:for-each select="rec[generate-id() = generate-id(key('recs', Pt)[1])]">
         <xsl:apply-templates select="key('recs', Pt)" />
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="rec">
    <Record>
      <xsl:copy-of select="Pt" />
      <DerivedPT>
        <xsl:value-of select="Pt" />
        <xsl:if test="Pt = '5'">
          <xsl:value-of select="concat('.',position())" />
        </xsl:if>
      </DerivedPT>
    </Record>
  </xsl:template>
</xsl:stylesheet>

Преимущество здесь в том, что если вы хотите, чтобы все записи имели логику, а не только "5", тогда вы просто удалите условие xsl:if.

И, если у вас большая структура, это должно быть более эффективным, чем постоянный подсчет количества предшествующих братьев и сестер.

1 голос
/ 21 мая 2019

Я бы тоже предпочел избежать повторного подсчета в обратном направлении и вместо этого сделать что-то вроде этого:

XSLT 1.0

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

<xsl:template match="rec">
    <Record>
        <PT>
            <xsl:value-of select="Pt" />
        </PT>
        <DerivedPT>
            <xsl:choose>
                <xsl:when test="Pt=5">
                    <xsl:text>5.</xsl:text>
                    <xsl:number count="rec[Pt=5]"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="Pt" />
                </xsl:otherwise>
            </xsl:choose>
        </DerivedPT>
    </Record>
</xsl:template>

</xsl:stylesheet>
1 голос
/ 21 мая 2019

Я установил номер подрывной деятельности в переменной для лучшей читабельности, но следующее сработало для ваших требований.Замените содержимое вашего <xsl:choose> следующим:

<xsl:when test="contains($pt,'5')">
  <xsl:variable name="thisSubversion" select="count(preceding-sibling::rec[Pt='5']) + 1" />
  <xsl:value-of select="concat($pt,'.', $thisSubversion)" />
</xsl:when>

Это позволяет вам просматривать только значения rec/Pt узлов, которые имеют значение "5".Надеюсь, это поможет!

https://xsltfiddle.liberty -development.net / 3NJ38Zz

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