XSLT 2.0 Тестирование имен элементов, начинающихся с определенного значения

Я немного огляделся, но не вижу очевидного ответа на свою проблему. Я уверен, что что-то не замечаю, но не знаю что.

Я провел некоторую предварительную обработку приведенного ниже XML, чтобы отредактировать некоторые имена элементов, и после предварительной обработки у меня есть таблица стилей XSL, которая выполняет простое преобразование идентичности. Однако мне интересно, есть ли способ избежать этапа предварительной обработки и выполнить все в одной таблице стилей. Основное различие между двумя входными данными XML состоит в том, что <subj*> стал <subj>.

Есть ли способ проверить имя элемента на предмет начального (или, я полагаю, конечного) значения? Большое спасибо за ваше время и предложения.

У меня есть ввод XML, который выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <row>
      <issueNumber>1.001</issueNumber>
      <subj1>Cats</subj1>
      <subj2>LOLCats</subj2>
      <subj3>Cheezburgers</subj3>
      <subj4></subj4>
   </row>
   <row>
      <issueNumber>2.001</issueNumber>
      <subj1>Cats</subj1>
      <subj2>LOLCats</subj2>
      <subj3>NOMS</subj3>
      <subj4>Cheezburger</subj4>
   </row>
   <row>
      <issueNumber>3.001</issueNumber>
      <subj1>NOMS</subj1>
      <subj2></subj2>
      <subj3></subj3>
      <subj4></subj4>
   </row>
</root>

Я обрабатываю его с помощью следующего XSL:

<?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:strip-space elements="*"/>

<xsl:template match="/">
    <xsl:apply-templates />
</xsl:template>

<xsl:template match="row">
    <!--<xsl:result-document href="{concat(issueNumber, '.xml')}">-->
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    <!--</xsl:result-document>-->    
</xsl:template>

<xsl:template match="issueNumber">
    <xsl:copy>
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>

<xsl:template match="subj">
    <xsl:choose>
        <xsl:when test="not(string(.))"></xsl:when>
        <xsl:when test="string(.)">
            <subject>
                <xsl:apply-templates />
            </subject>
        </xsl:when>
    </xsl:choose>
</xsl:template>


person CanOfBees    schedule 04.04.2012    source источник


Ответы (2)


Если я правильно понимаю вопрос, вы можете сделать что-то вроде этого:

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

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

  <xsl:template match="*[starts-with(name(),'subj')]">
    <subj>
      <xsl:if test="string(.)">
        <subject>
          <xsl:apply-templates/>
        </subject>
      </xsl:if>
    </subj>
  </xsl:template>

</xsl:stylesheet>

Используя ваш ввод XML (исправленный, чтобы он был правильно сформирован):

<root>
  <row>
    <issueNumber>1.001</issueNumber>
    <subj1>Cats</subj1>
    <subj2>LOLCats</subj2>
    <subj3>Cheezburgers</subj3>
    <subj4></subj4>
  </row>
  <row>
    <issueNumber>2.001</issueNumber>
    <subj1>Cats</subj1>
    <subj2>LOLCats</subj2>
    <subj3>NOMS</subj3>
    <subj4>Cheezburger</subj4>
  </row>
  <row>
    <issueNumber>3.001</issueNumber>
    <subj1>NOMS</subj1>
    <subj2></subj2>
    <subj3></subj3>
    <subj4></subj4>
  </row>
</root>

Производит следующий вывод:

<root>
   <row>
      <issueNumber>1.001</issueNumber>
      <subj>
         <subject>Cats</subject>
      </subj>
      <subj>
         <subject>LOLCats</subject>
      </subj>
      <subj>
         <subject>Cheezburgers</subject>
      </subj>
      <subj/>
   </row>
   <row>
      <issueNumber>2.001</issueNumber>
      <subj>
         <subject>Cats</subject>
      </subj>
      <subj>
         <subject>LOLCats</subject>
      </subj>
      <subj>
         <subject>NOMS</subject>
      </subj>
      <subj>
         <subject>Cheezburger</subject>
      </subj>
   </row>
   <row>
      <issueNumber>3.001</issueNumber>
      <subj>
         <subject>NOMS</subject>
      </subj>
      <subj/>
      <subj/>
      <subj/>
   </row>
</root>
person Daniel Haley    schedule 04.04.2012
comment
Я отредактировал ввод XML - недостаточно далеко </root> - извините за это. ваша таблица стилей ближе всего к лаконичному использованию xsl:template match="*[starts-with...]". спасибо, большое, за помощь! - person CanOfBees; 05.04.2012

Вы ищете что-то вроде "регулярного выражения" в XSLT? Если да, то эта ссылка может быть вам очень полезна: http://www.w3.org/TR/xslt20/#regular-expressions

Однако это решение работает только в XSLT 2.0. Вы можете потерять совместимость со старыми версиями XSLT.

person Dominik M.    schedule 04.04.2012
comment
спасибо, Доминик! проблема была не в регулярном выражении, а в правильном использовании starts-with() в xsl:template match="...". - person CanOfBees; 05.04.2012
comment
также - спасибо за ссылку на спецификацию - это хорошее напоминание о том, что доступно. - person CanOfBees; 05.04.2012
comment
Год, технические характеристики часто являются лучшим ориентиром. - person Dominik M.; 05.04.2012