Identifying data type for every element inside a X

2019-08-04 07:14发布

问题:

As a follow up to this answer, is there a way I can figure out if the data type of the XML values? XSL transformation doc in java

eg:

<root>
<test>
  true
</test>
<test1>
  1
</test1>
<test2>
  "abc"
</test2>
</root>

My thought:

<xsl:template match="/">
    <object>
        <xsl:for-each select="//*[normalize-space(.)]">
                <xsl:choose>        
                    <xsl:when test="contains(., 3)">//  want to check for Integer
                        <Integer name="{name()}">
                            <xsl:value-of select="."/>
                        </Integer>
                    </xsl:when>
                    <xsl:otherwise>
                        //check for string, boolean
                    </xsl:otherwise>
                </xsl:choose>
        </xsl:for-each>
    </object>
</xsl:template>

I want to know how I would be able to identify in XSL the data type of 1,"abc",true as integer,string and boolean? If someone can help me understand how normalize-space(.) works it would be very helpful (:

Any help would be greatly appreciated.

回答1:

You could use castable as in XSLT 2.0 to check if the value of the element is castable as either xs:integer or xs:boolean (or any of the other xs datatypes).

Example...

XML Input

<root>
    <test>
        true
    </test>
    <test1>
        1
    </test1>
    <test2>
        "abc"
    </test2>
</root>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <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="test|test1|test2">
        <xsl:variable name="type">
            <xsl:choose>
                <xsl:when test="normalize-space() castable as xs:integer">
                    <xsl:text>Integer</xsl:text>
                </xsl:when>
                <xsl:when test="normalize-space() castable as xs:boolean">
                    <xsl:text>Boolean</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>String</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:element name="{$type}">
            <xsl:attribute name="name" select="name()"/>
            <xsl:value-of select="normalize-space()"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

XML Output

<root>
   <Boolean name="test">true</Boolean>
   <Integer name="test1">1</Integer>
   <String name="test2">"abc"</String>
</root>

If your XML is using a schema and your processor is schema aware, you could also use instance of to check the type.

Also, you could use an if statement instead of the xsl:choose if you find it easier to read...

<xsl:variable name="type" select="
    if (normalize-space() castable as xs:integer) then 
        'Integer' 
    else if (normalize-space() castable as xs:boolean) then 
        'Boolean' 
    else 
        'String'
"/>


标签: xml xslt