Открепить XML-документ на основе атрибутов

StackOverflow https://stackoverflow.com/questions/86919

  •  01-07-2019
  •  | 
  •  

Вопрос

У меня есть простой xml-документ, который выглядит как следующий фрагмент.Мне нужно написать XSLT-преобразование, которое в основном "отключает" этот документ на основе некоторых атрибутов.

<?xml version="1.0" encoding="utf-8" ?>
<root xmlns:z="foo">
    <z:row A="1" X="2" Y="n1" Z="500"/>
    <z:row A="2" X="5" Y="n2" Z="1500"/>
</root>

Это то, чего я ожидаю от результата -

<?xml version="1.0" encoding="utf-8" ?>
<root xmlns:z="foo">
    <z:row A="1" X="2"  />
    <z:row A="1" Y="n1" />
    <z:row A="1" Z="500"/>
    <z:row A="2" X="5" />
    <z:row A="2" Y="n2"/>
    <z:row A="2" Z="1500"/>
</root>

Ценю вашу помощь.

Это было полезно?

Решение

<xsl:template match="row">
    <row A="{$A}" X="{$X}" />
    <row A="{$A}" Y="{$Y}" />
    <row A="{$A}" Z="{$Z}" />
</xsl:template>

Плюс очевидный шаблон.

Другие советы

Вот полная таблица стилей, которая вам нужна (поскольку пространства имен важны):

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:z="foo">

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

<xsl:template match="z:row">
  <xsl:variable name="A" select="@A" />
  <xsl:for-each select="@*[local-name() != 'A']">
    <z:row A="{$A}">
      <xsl:attribute name="{local-name()}">
        <xsl:value-of select="." />
      </xsl:attribute>
    </z:row>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Я предпочитаю использовать элементы literal result (например <z:row>) , а не <xsl:element> и шаблоны значений атрибутов (те {}s в значениях атрибутов), а не <xsl:attribute> там, где это возможно, поскольку это сокращает код и облегчает просмотр структуры результирующего документа, который вы создаете.Другие предпочитают <xsl:element> и <xsl:attribute> потому что тогда все является инструкцией XSLT.

Если вы используете XSLT 2.0, есть пара синтаксических тонкостей, которые помогут, а именно except оператор в XPath и возможность использовать select атрибут непосредственно на <xsl:attribute>:

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  xmlns:z="foo">

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

<xsl:template match="z:row">
  <xsl:variable name="A" as="xs:string" select="@A" />
  <xsl:for-each select="@* except @A">
    <z:row A="{$A}">
      <xsl:attribute name="{local-name()}" select="." />
    </z:row>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Это более сложный, но и более общий метод:

<xsl:template match="z:row">
    <xsl:variable name="attr" select="@A"/>
    <xsl:for-each select="@*[(local-name() != 'A')]">
        <xsl:element name="z:row">
            <xsl:copy-of select="$attr"/>
            <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
        </xsl:element>
    </xsl:for-each>
</xsl:template>

Вот небольшой способ применения грубой силы:

<xsl:template match="z:row">
    <xsl:element name="z:row">
        <xsl:attribute name="A">
            <xsl:value-of select="@A"/>
        </xsl:attribute>
        <xsl:attribute name="X">
            <xsl:value-of select="@X"/>
        </xsl:attribute>
    </xsl:element>
    <xsl:element name="z:row">
        <xsl:attribute name="A">
            <xsl:value-of select="@A"/>
        </xsl:attribute>
        <xsl:attribute name="Y">
            <xsl:value-of select="@Y"/>
        </xsl:attribute>
    </xsl:element>
    <xsl:element name="z:row">
        <xsl:attribute name="A">
            <xsl:value-of select="@A"/>
        </xsl:attribute>
        <xsl:attribute name="Z">
            <xsl:value-of select="@Z"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>


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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top