преобразование соответствия шаблону xslt - PullRequest
3 голосов
/ 10 сентября 2010

Как я могу преобразовать следующий XML с помощью XSLT из этого:

<root>
    <list>
        <item label="21(1)">some text</item>
        <item label="(2)">some text</item>
    </list>
    <list>
        <item label="a">some text</item>
        <item label="b">some text</item>
    </list>
</root>

к этому:

<root>
    <list label="21">
        <item label="(1)">some text</item>
        <item label="(2)">some text</item>
    </list>
    <list>
        <item label="a">some text</item>
        <item label="b">some text</item>
    </list>
</root>

Таким образом, если перед скобкой в ​​атрибуте label первого item стоит число перед скобкой, это число необходимо добавить в качестве значения атрибута label для родительского элемента list.

Шаблон, соответствующий атрибуту, будет выглядеть примерно так:

/(\d+)\([^\)]+\)/

Ответы [ 4 ]

1 голос
/ 10 сентября 2010

Как упоминал Николаус, вы можете использовать функции substring-before и substring-after XPath.Пример преобразования XSL будет выглядеть так:

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

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

  <xsl:template match="list">
    <list>
      <xsl:variable name="prefix" select="substring-before(./item/@label, '(')" />
      <xsl:if test="$prefix != '' and number($prefix)">
        <xsl:attribute name="label">
          <xsl:value-of select="substring-before(./item/@label, '(')"/>
        </xsl:attribute>
      </xsl:if>
      <xsl:apply-templates />
    </list>
  </xsl:template>

  <xsl:template match="item">
    <item>
      <xsl:attribute name="label">
        <xsl:variable name="prefix" select="substring-before(@label, '(')" />
        <xsl:choose>
          <xsl:when test="$prefix != '' and number($prefix)">
            <xsl:value-of select="concat('(', substring-after(@label, '('))"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="@label"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>
      <xsl:apply-templates />
    </item>
  </xsl:template>
</xsl:stylesheet>
1 голос
/ 10 сентября 2010

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:strip-space elements="*"/>
 <xsl:template match="node()|@*" name="identity">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
 </xsl:template>
 <xsl:template match="item[1][boolean(number(substring-before(@label,'(')))]">
    <xsl:attribute name="label">
        <xsl:value-of select="substring-before(@label,'(')"/>
    </xsl:attribute>
    <xsl:call-template name="identity"/>
 </xsl:template>
 <xsl:template match="item[1]/@label[boolean(number(substring-before(.,'(')))]">
    <xsl:attribute name="label">
        <xsl:value-of select="concat('(',substring-after(.,'('))"/>
    </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

Вывод:

<root>
    <list label="21">
        <item label="(1)">some text</item>
        <item label="(2)">some text</item>
    </list>
    <list>
        <item label="a">some text</item>
        <item label="b">some text</item>
    </list>
</root>

Редактировать : компактный предикат.

Редактировать 2 : Номер теста до парентез.Explicity полосы пустого пространства только узлами.

1 голос
/ 10 сентября 2010

вы можете использовать функцию xslt substring-before , чтобы получить подстроку перед '('

0 голосов
/ 10 сентября 2010

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

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

 <xsl:template match=
  "list[number(substring-before(item[1]/@label, '('))
       =
       number(substring-before(item[1]/@label, '('))
       ]">
  <list label="{substring-before(item[1]/@label, '(')}">
    <xsl:apply-templates select="node()|@*"/>
  </list>
 </xsl:template>

 <xsl:template match=
   "item[1]/@label[number(substring-before(., '('))
           =
           number(substring-before(., '('))
           ]">
   <xsl:attribute name="label">
    <xsl:value-of select="concat('(',substring-after(.,'('))"/>
   </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

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

<root>
    <list>
        <item label="21(1)">some text</item>
        <item label="(2)">some text</item>
    </list>
    <list>
        <item label="a">some text</item>
        <item label="b">some text</item>
    </list>
</root>

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

<root>
    <list label="21">
        <item label="(1)">some text</item>
        <item label="(2)">some text</item>
    </list>
    <list>
        <item label="a">some text</item>
        <item label="b">some text</item>
    </list>
</root>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...