Добавьте два hexBinarys с XPATH 1.0 - PullRequest
1 голос
/ 16 июня 2010

мой 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>. Но обычный + возвращает NaN, а sum() ожидает только один параметр. XSLT и XPATH довольно хороши, но мне на нервы, что простые операции, такие как добавление двух шестнадцатеричных значений, просто не работают так просто, как следовало бы.

Ответы [ 3 ]

1 голос
/ 17 июня 2010

Я никогда не разрабатывал функцию 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> 

Редактировать: Недавно я только что понял, что здесь есть перекрестные ссылки.Поэтому следует использовать ключи.

1 голос
/ 16 июня 2010

Вот решение , которое объединяет преобразование шестнадцатеричного значения в десятичное значение, представленное в 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
0 голосов
/ 18 марта 2014

Вот как я делаю это без использования 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) 
)

Оба предполагают ваш гексцифры всегда имеют две цифры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...