Я пытаюсь сортировать по тексту - XSLT - PullRequest
3 голосов
/ 30 апреля 2020

Я пытаюсь сортировать по тексту, первый текст должен быть в верхнем регистре, тогда как другие начинаются с заглавных букв или маленькой буквы. Ввод XML

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
        <p content-type="emCase"><named-content content-type="emEntry">B</named-content></p>
        <p content-type="emCase"><named-content content-type="emEntry">BTS, USA, Inc. v Executive Perspectives, LLC (Conn. Super, Oct. 16, 2014, No. X10CV116010685) 2014 Conn Super Lexis 2644, aff’d (Conn App 2016) 142 A3d 342:</named-content></p>
        <p content-type="emCase"><named-content content-type="emEntry">buySAFE, Inc. v Google, Inc. (Fed Cir 2014) 765 F3d 1350:</named-content></p>
        <p content-type="emCase"><named-content content-type="emEntry">Babcock v Butler County (3d Cir 2015) 806 F3d 153:</named-content></p>
        <p content-type="emCase"><named-content content-type="emEntry">Buxbom v Smith (1944) 23 C2d 535:</named-content></p>
        <p content-type="emCase"><named-content content-type="emEntry">Byrd v Roadway Express, Inc. (5th Cir 1982) 687 F2d 85:</named-content></p>
        <p content-type="emCase"><named-content content-type="emEntry">B.K.B. v Maui Police Dep’t (9th Cir 2002) 276 F3d 1091:</named-content></p>
    </root>

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

    <root>
    <p content-type="emCase"><named-content content-type="emEntry">B</named-content></p>
    <p content-type="emCase"><named-content content-type="emEntry">B.K.B. v Maui Police Dep’t (9th Cir 2002) 276 F3d 1091:</named-content></p>
    <p content-type="emCase"><named-content content-type="emEntry">BTS, USA, Inc. v Executive Perspectives, LLC (Conn. Super, Oct. 16, 2014, No. X10CV116010685) 2014 Conn Super Lexis 2644, aff’d (Conn App 2016) 142 A3d 342:</named-content></p>
    <p content-type="emCase"><named-content content-type="emEntry">Babcock v Butler County (3d Cir 2015) 806 F3d 153:</named-content></p>
    <p content-type="emCase"><named-content content-type="emEntry">Buxbom v Smith (1944) 23 C2d 535:</named-content></p>
    <p content-type="emCase"><named-content content-type="emEntry">buySAFE, Inc. v Google, Inc. (Fed Cir 2014) 765 F3d 1350:</named-content></p>
    <p content-type="emCase"><named-content content-type="emEntry">Byrd v Roadway Express, Inc. (5th Cir 1982) 687 F2d 85:</named-content></p>
    </root>

Мой XSLT-код

    <xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="root">
    <xsl:copy>
        <xsl:for-each select="p[named-content[@content-type='emEntry'][matches(., '^([A-Za-z]+)')]]">
            <xsl:sort select="if(named-content[@content-type='emEntry' and matches(., '^([A-Z]+)')]) then named-content[@content-type='emEntry' and matches(., '^([A-Z]+)')] else upper-case(named-content[@content-type='emEntry'])" data-type="text" order="ascending"/>
            <xsl:text>&#x0A;</xsl:text>
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

Может ли кто-нибудь помочь мне, где мой неправильный код?

Ответы [ 3 ]

2 голосов
/ 02 мая 2020

Соответствует ли следующее вашим требованиям? (Требования было трудно понять. Я предполагаю, что есть более простой и быстрый код XSLT для выполнения sh этой задачи ...)

Он оценивает для данного ввода ожидаемый результат https://xsltfiddle.liberty-development.net/pNmC4J7

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="#all"
    version="2.0">

  <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>

    <xsl:key name="psStartingWithChar" match="p" use="upper-case(substring(translate(named-content/text(), translate(named-content/text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', ''), ''),1,1))"/>

    <xsl:template match="root">
        <xsl:variable name="ctxt">
            <xsl:copy-of select="."/>
        </xsl:variable>

        <xsl:variable name="temp">
            <xsl:for-each select="string-to-codepoints('ABCDEFGHIJKLMNOPQRSTUVWXYZ')">
                <xsl:variable name="ch" select="codepoints-to-string(.)"/>

                <xsl:variable name="root">
                    <xsl:for-each select="$ctxt">
                        <root>
                            <xsl:for-each select="key('psStartingWithChar',$ch)">
                                <xsl:copy-of select="."/>
                            </xsl:for-each>
                        </root>
                    </xsl:for-each>
                </xsl:variable>

                <xsl:for-each select="$root/root">
                    <xsl:copy>
                        <xsl:for-each select="p[named-content[@content-type='emEntry'][string-length(.)=1 or matches(translate(., translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', ''), ''), '^([^a-z]{2,})')]]">
                            <xsl:sort data-type="text" order="ascending"/>
                            <xsl:copy>
                                <xsl:apply-templates select="@*|node()"/>
                            </xsl:copy>
                        </xsl:for-each>
                        <xsl:for-each select="p[named-content[@content-type='emEntry'][not(string-length(.)=1 or matches(translate(., translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', ''), ''), '^([^a-z]{2,})'))]]">
                            <xsl:sort data-type="text" case-order= "upper-first" order="ascending"/>
                            <xsl:copy>
                                <xsl:apply-templates select="@*|node()"/>
                            </xsl:copy>
                        </xsl:for-each>
                    </xsl:copy>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:variable>

        <root>
            <xsl:copy-of select="$temp/root/*"/>
        </root>
   </xsl:template>

</xsl:stylesheet>
0 голосов
/ 30 апреля 2020

Чтобы отсортировать заглавные буквы перед строчными, используйте атрибут case-order xsl:sort.

Вот упрощенный пример:

XSLT

<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:template match="/root">
    <xsl:copy>
        <xsl:for-each select="p">
            <xsl:sort select="named-content" data-type="text" order="ascending" case-order= "upper-first"/>
            <xsl:copy>
                <xsl:apply-templates/>
            </xsl:copy>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Результат

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <p>B.K.B. v Maui Police Dep’t (9th Cir 2002) 276 F3d 1091:</p>
  <p>BTS, USA, Inc. v Executive Perspectives, LLC (Conn. Super, Oct. 16, 2014, No. X10CV116010685) 2014 Conn Super Lexis 2644, aff’d (Conn App 2016) 142 A3d 342:</p>
  <p>Babcock v Butler County (3d Cir 2015) 806 F3d 153:</p>
  <p>Buxbom v Smith (1944) 23 C2d 535:</p>
  <p>Byrd v Roadway Express, Inc. (5th Cir 1982) 687 F2d 85:</p>
  <p>buySAFE, Inc. v Google, Inc. (Fed Cir 2014) 765 F3d 1350:</p>
</root>

Добавлено:

Я тоже не понимаю, какую логику c вы хотите реализовать, чтобы получить вывод, который вы показываете.

Я могу получить тот же вывод, отсортировав узлы в следующем порядке:

  • узлы, начинающиеся с инициалов, идут первыми;
  • затем сортировать по алфавиту, игнорируя регистр.

XSLT 2.0

<xsl:stylesheet version="2.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="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="/root">
    <xsl:copy>
        <xsl:apply-templates select="p">
            <xsl:sort select="number(matches(named-content, '^[A-Z](\.|[A-Z]|$)'))" data-type="number" order="descending"/>
            <xsl:sort select="named-content" data-type="text" order="ascending" lang="en"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

Демо : https://xsltfiddle.liberty-development.net/a9GPfN

</xsl:stylesheet>
0 голосов
/ 30 апреля 2020

Не уверен, что я получил ваш вопрос, вот что вы пытаетесь сделать:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="root">
      <xsl:copy>
          <xsl:apply-templates select="p">
              <xsl:sort select="named-content"/>
          </xsl:apply-templates>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Посмотрите, как это работает здесь: https://xsltfiddle.liberty-development.net/bEzknsV

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