XSLT для каждого пространства имен - PullRequest
0 голосов
/ 29 апреля 2020

Я использую for-each в моем шаблоне XSLT.

Это мой пример ввода XML:

<products>
  <data>
    <label_1>some_label1</label_1>
    <label_2>some_label2</label_2>
    <values>
      <a>a</a>
      <b>b</b>
    </values>
  </data>
  <data>
    <label_1>some_label1</label_1>
    <label_2>some_label2</label_2>
    <values>
      <c>c</c>
      <d>d</d>
    </values>
  </data>
</products>

Теперь на основе моего шаблона:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http:/example.com/ns">
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="data">
        <data>
            <xsl:variable name="values" select="values" />
            <xsl:for-each select="$values">
                <xsl:apply-templates select="@*|node()" />
            </xsl:for-each>
        </data>
    </xsl:template>
</xsl:stylesheet>

Я получаю только <values></values>, и это нормально для меня.

Это мой вывод:

<products>
  <data>
    <a>a</a>
    <b>b</b>
  </data>
  <data>
    <c>c</c>
    <d>d</d>
  </data> 
</products>

Что мне нужно в моем выводе, так это пространство имен:

<products>
  <data>
    <ns:a>a</ns:a>
    <ns:b>b</ns:b>
  </data>
  <data>
    <ns:c>c</ns:c>
    <ns:d>d</ns:d>
  </data> 
</products>

Итак, я понимаю, что «каждый элемент значений применяется шаблоном». Как я могу добавить пространство имен?

Ответы [ 2 ]

1 голос
/ 29 апреля 2020

Вы можете получить вывод, аналогичный тому, который вы показываете (хотя и правильно сформированный), используя:

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="*"/>

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

<xsl:template match="data">
    <xsl:copy>
        <xsl:apply-templates select="values/*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="values/*">
    <xsl:element name="ns:{local-name()}" namespace="http:/example.com/ns">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

Или, если вы предпочитаете:

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

<xsl:template match="/products">
    <products>
        <xsl:for-each select="data">
            <xsl:copy>
                <xsl:for-each select="values/*">
                    <xsl:element name="ns:{local-name()}">
                        <xsl:value-of select="."/>
                    </xsl:element>
                </xsl:for-each>
            </xsl:copy>
        </xsl:for-each>
    </products>
</xsl:template>

</xsl:stylesheet>

Замените http:/example.com/ns на свой URI пространства имен.

0 голосов
/ 29 апреля 2020

Кредиты

Этот ответ следует методике, использованной в этом SO-ответе на аналогичную проблему.

Решение

Добавить информацию о пространстве имен всем потомкам указанных элементов c. Дополните таблицу стилей шаблоном, соответствующим этому набору узлов:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns="http://my.ns.uri"
>
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="data">
        <data>
            <xsl:variable name="values" select="values" />
            <xsl:for-each select="$values">
                <xsl:apply-templates select="@*|node()" />
            </xsl:for-each>
        </data>
    </xsl:template>

    <!--
        Added template.
    -->
    <xsl:template match="data//*">
        <xsl:element name="ns:{name()}" namespace="http://my.ns.uri">
            <xsl:for-each select=".">
                <xsl:apply-templates select="@*|node()" />
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...