在xslt中按大写字母拆分XML节点的名称

时间:2016-08-14 11:29:59

标签: xml xslt

我有这样的XML:

<process id="Process_1">
  <exclusiveGateway id="ExclusiveGateway_03b639w" />
  <startEvent id="StartEvent_0nmzsw0" />
  <sendTask id="Task_13s9uob"/>
  <userTask id="Task_1v0riz3" />
</process>

我需要使用 xslt

将其转换为此内容
<process id="Process_1">
  <Gateway type="exclusive" id="ExclusiveGateway_03b639w" />
  <Event type="start" id="StartEvent_0nmzsw0" />
  <Task type="send" id="Task_13s9uob"/>
  <Task type="user" id="Task_1v0riz3" />
</process>

我想我可以使用tokenize功能,但我不知道如何分隔令牌。

如果有人可以解释这个问题的解决方案,那将非常有用。

感谢。

2 个答案:

答案 0 :(得分:2)

假设使用像Saxon 9这样的XSLT 2.0处理器,你可以使用

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

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

    <xsl:template match="*[matches(local-name(), '^\p{Ll}+\p{Lu}')]">
        <xsl:element name="{replace(local-name(), '^\p{Ll}+', '')}">
            <xsl:attribute name="type" select="replace(local-name(), '\p{Lu}.*', '')"/>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

http://xsltransform.net/jz1PuNM在线。

答案 1 :(得分:2)

要在XSLT 1.0中执行此操作,请尝试以下方法:

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="/process/*">
    <xsl:variable name="split" select="string-length(substring-before(translate(name(), 'BCDEFGHIJKLMNOPQRSTUVWXYZ', 'AAAAAAAAAAAAAAAAAAAAAAAAA'), 'A'))" />
    <xsl:element name="{substring(name(), $split + 1)}">
        <xsl:attribute name="type">
            <xsl:value-of select="substring(name(), 1, $split)"/>
        </xsl:attribute>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

请注意,这假设需要根据所示处理根process元素的所有(且唯一)子元素。

P.S。如果您知道输入XML的结构,那么显式转换单个元素会更加健壮,例如:

<xsl:template match="exclusiveGateway">
     <Gateway type="exclusive">
        <xsl:apply-templates select="@* | node()"/>
    </Gateway>
</xsl:template>