通过XSLT转换XML文件,转换罗马数字以更正阿拉伯数字

时间:2017-07-24 23:15:53

标签: xml xslt xslt-1.0 transform xslt-2.0

我有以下xml输入:

<root>
    <calc>
        <roman>XLIV</roman>
    </calc>
    <calc>
        <roman>DCXI</roman>
    </calc>
</root>

我想输出以下内容:

<root>
    <calc>
        <roman>XLIV</roman>
        <arab>44</arab>
    </calc>
    <calc>
        <roman>DCXI</roman>
        <arab>611</arab>
    </calc>
</root>

编写XSLT。到目前为止,我编写了这个XSLT,但还需要做些什么才能输出正确的结果?

<xsl:transform
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:num="http://whatever"
  version="2.0">

  <xsl:output method="xml" version="1.0"
    encoding="UTF-8" indent="yes"/>


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

  <xsl:function name="num:roman" as="xs:string">
    <xsl:param name="value" as="xs:integer"/>
    <xsl:number value="$value" format="i"/>
  </xsl:function>

</xsl:transform>

验证罗马数字的额外规则:

有几条规则适用于从罗马数字中减去金额:

  • 仅减去10的幂(I,X或C,但不是V或L)

Ex:对于95,不要写VC(100 - 5)。 DO写XCV(XC + V或90 + 5)

  • 仅从另一个
  • 中减去一个数字

Ex:对于13,不要写IIXV(15 - 1 - 1)。 DO写XIII(X + I + I + I或10 + 3)

  • 不要从超过10倍的数字中减去一个数字(也就是说,你可以从10 [IX]中减去1但从20减去1 - 没有IXX这样的数字。)

例如:99,不要写IC(C - I或100 - 1)。 请写XCIX(XC + IX或90 + 9)

1 个答案:

答案 0 :(得分:3)

您必须更加明确功能,如 XSLT 2.0

中所示
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:num="http://whatever"
    version="2.0" exclude-result-prefixes="xs num">

    <xsl:output method="xml" version="1.0"
        encoding="UTF-8" indent="yes"/>


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

    <xsl:template match="roman">
        <xsl:copy-of select="."/>
        <arab><xsl:choose>
            <xsl:when test="matches(., '[^IVXLCDM]|II[^I]|IIII+|XXXX+|CCCC+|V[^I]|[^I]?I[VIX][IVXLCDM]|[^I]?I[^VIX]')">
                <xsl:comment>Your Message about Not Roman Data</xsl:comment>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="num:roman(., 0)"></xsl:value-of>
            </xsl:otherwise>
        </xsl:choose>
        </arab>
    </xsl:template>

    <xsl:function name="num:roman" as="xs:integer">
        <xsl:param name="r" as="xs:string"/>
        <xsl:param name="s"/>
        <xsl:choose>
            <xsl:when test="ends-with($r,'CM')">
                <xsl:sequence select="900 + num:roman(substring($r,1,string-length($r)-2), 900)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'M')">
                <xsl:sequence select="1000+ num:roman(substring($r,1,string-length($r)-1), 1000)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'CD')">
                <xsl:sequence select="400+ num:roman(substring($r,1,string-length($r)-2), 400)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'D')">
                <xsl:sequence select="500+ num:roman(substring($r,1,string-length($r)-1), 500)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'XC')">
                <xsl:sequence select="90+ num:roman(substring($r,1,string-length($r)-2), 90)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'C')">
                <xsl:sequence select="(if(100 ge number($s)) then 100 else -100)+ num:roman(substring($r,1,string-length($r)-1), 100)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'XL')">
                <xsl:sequence select="40+ num:roman(substring($r,1,string-length($r)-2), 40)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'L')">
                <xsl:sequence select="50+ num:roman(substring($r,1,string-length($r)-1), 50)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'IX')">
                <xsl:sequence select="9+ num:roman(substring($r,1,string-length($r)-2), 9)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'X')">
                <xsl:sequence select="(if(10 ge number($s)) then 10 else -10) + num:roman(substring($r,1,string-length($r)-1), 10)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'IV')">
                <xsl:sequence select="4+ num:roman(substring($r,1,string-length($r)-2), 4)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'V')">
                <xsl:sequence select="5+ num:roman(substring($r,1,string-length($r)-1), 5)"/>
            </xsl:when>
            <xsl:when test="ends-with($r,'I')">
                <xsl:sequence select="(if(1 ge number($s)) then 1 else -1)+ num:roman(substring($r,1,string-length($r)-1), 1)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:sequence select="0"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>

</xsl:transform>
相关问题