添加两个hexBinarys使用XPath 1.0(Add two hexBinarys with

2019-10-23 05:43发布

我的XML文档看起来有点像(数值都xsl:hexBinary ):

<Offsets>  
    <Offset>  
        <Name>ErrorOffset</Name>  
        <Value>DD</Value>  
    </Offset>  
    <Offset>  
        <Name>OtherOffset</Name>  
        <Value>FF</Value>  
    </Offset>  
</Offsets>  
<Value>  
    <Name>Error1</Name>  
    <Code>01</Code>  
</Value>
<Value>  
    <Name>Error2</Name>  
    <Code>02</Code>  
    <Offset>ErrorOffset</Offset>  
</Value>

现在我想这个转换为新的XML文件:

<Value>  
    <Name>Error1</Name>  
    <Code>01</Code>  
</Value>
<Value>  
    <Name>Error2</Name>  
    <Code>DF</Code>  
</Value>

所有应该发生,它是将<Offset>基本<Value> 。 但普通+返回NaNsum()预计,只有一个参数。 XSLT和XPath是相当不错的,但它会在我的神经,像增加了两个十六进制值的简单的操作只是不因为它应该工作一样简单。

Answer 1:

我从来没有制定了十六进制数一conersión功能。 这是一个函数,它是相反Dimitre的例子的一个例子。 我认为这将有可能进一步降低样式表。 还值得一提的是,变换函数可以被参数化并且推广到任何碱。

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

<xsl:key name="offset" match="Offset/Value" use="../Name" />     

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

<xsl:template match="Offsets|Offset" />

<xsl:template match="Code/text()[../../Offset]" >
    <xsl:variable name="code">
        <xsl:call-template name="hex2dec">
            <xsl:with-param name="num" select="." />
        </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="offset">
        <xsl:call-template name="hex2dec">
            <xsl:with-param name="num" select="key('offset',../../Offset)" />
        </xsl:call-template>
    </xsl:variable>
    <xsl:call-template name="dec2hex">
        <xsl:with-param name="dec" select="$code + $offset" />
    </xsl:call-template>
</xsl:template>

<xsl:template name="hex2dec">
    <xsl:param name="num" />
    <xsl:param name="hex" select="translate($num,'abcdef','ABCDEF')"/>
    <xsl:param name="acc" select="0" />
    <xsl:choose>
        <xsl:when test="string-length($hex)">
            <xsl:call-template name="hex2dec">
                <xsl:with-param name="hex" select="substring($hex,2,string-length($hex))" />
                <xsl:with-param name="acc" select="$acc * 16 + string-length(substring-before('0123456789ABCDEF',substring($hex,1,1)))" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$acc" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="dec2hex">
    <xsl:param name="dec" />
    <xsl:if test="$dec >= 16">
        <xsl:call-template name="dec2hex">
            <xsl:with-param name="dec" select="floor($dec div 16)" />
        </xsl:call-template>
    </xsl:if>
    <xsl:value-of select="substring('0123456789ABCDEF', ($dec mod 16) + 1, 1)" />
</xsl:template>

</xsl:stylesheet> 

编辑:最近,我只是在这里实现交叉引用。 因此,应使用的密钥。



Answer 2:

这里是一个解决方案 ,它结合了十六进制的转换为十进制中的值作为本FXSL借非FXSL模板为十进制的转换的交互为十六进制。

这一转变

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:func-transform2="f:func-transform2"
exclude-result-prefixes="xsl f func-transform2"
>
   <xsl:import href="transform-and-sum.xsl"/>
   <xsl:import href="hex-to-decimal.xsl"/>

   <!-- to be applied on testTransform-and-sum2.xml -->

   <xsl:output method="text"/>

   <func-transform2:func-transform2/>

    <xsl:template match="/">
      <xsl:variable name="vdecSum">
       <xsl:call-template name="transform-and-sum">
        <xsl:with-param name="pFuncTransform" 
                        select="document('')/*/func-transform2:*[1]"/>
        <xsl:with-param name="pList" select="/*/*"/>
       </xsl:call-template>
      </xsl:variable>

      <xsl:call-template name="toHex">
       <xsl:with-param name="decimalNumber" select="$vdecSum"/>
      </xsl:call-template>

    </xsl:template>

    <xsl:template match="func-transform2:*" mode="f:FXSL">
      <xsl:param name="arg1" select="0"/>

      <xsl:call-template name="hex-to-decimal">
        <xsl:with-param name="pxNumber" select="$arg1"/>
      </xsl:call-template>
    </xsl:template>

  <xsl:template name="toHex">
    <xsl:param name="decimalNumber" />
    <xsl:if test="$decimalNumber >= 16">
      <xsl:call-template name="toHex">
        <xsl:with-param name="decimalNumber" select="floor($decimalNumber div 16)" />
      </xsl:call-template>
    </xsl:if>
    <xsl:value-of select="substring($hexDigits, ($decimalNumber mod 16) + 1, 1)" />
</xsl:template>

</xsl:stylesheet>

当应用这个XML文档上

<t>
 <hexNum>1001</hexNum>
 <hexNum>0FA3</hexNum>
</t>

产生正确的,想要的结果

1FA4


Answer 3:

这就是我要做的事,而无需使用XSLT:

十六进制数

160 * translate(substring(Offsets/Offset/Value,1,1),
                  '0123456789ABCDEFabcdef',
                  '0000000000111111111111')         +
16 * translate(substring(Offsets/Offset/Value,1,1),
                  '0123456789ABCDEFabcdef',
                  '0123456789012345012345')         +
10 * translate(substring(Offsets/Offset/Value,2,1),
                  '0123456789ABCDEFabcdef',
                  '0000000000111111111111')         +
translate(substring(Offsets/Offset/Value,2,1),
                  '0123456789ABCDEFabcdef',
                  '0123456789012345012345')

反向功能比较简单:

concat(
  substring('0123456789ABCDEF', valueDecimal   / 16 ,1)  ,
  substring('0123456789ABCDEF', valueDecimal mod 16 ,1) 
)

这两种假设你的十六进制数字总是有两个数字。



文章来源: Add two hexBinarys with XPATH 1.0
标签: xslt xpath sum hex