2010-08-25 6 views
0

моего входного файл XML выглядитизвлечение значения XML динамически с помощью функции XSL

<root> 
    <sub> 
    <element1 value="abc"/> 
     <element2 value="123"/> 
    </sub> 
    <sub1> 
    <element1 value="ert"/> 
    <element2 value="abc"/> 
    </sub1> 
</root> 

я нужна функция XSLT, которая читает ниже файл XML и вытягивает значение выражения XPath, указанное на карте/домен/экземпляр/@ XPath от вышеуказанный файл

<map> 
    <domain> 
    <instance xpath="root/sub/element1/@value" length="2"/> 
    </domain> 
    <domain> 
     <instance xpath="root/sub1/element2/@value" length="3"/> 
    </domain> 
</map> 

Мне нужна функция, которая проверяет XSLT длину, указанную для каждого выражения XPath против входящего файла XML.

Если он не работает по длине, он должен восстановить ложь.

ответ

3

Это XSLT-таблица стилей 1.0:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:variable name="document"> 
     <root> 
      <sub> 
       <element1 value="abc"/> 
       <element2 value="123"/> 
      </sub> 
      <sub1> 
       <element1 value="ert"/> 
       <element2 value="abc"/> 
      </sub1> 
     </root> 
    </xsl:variable> 
    <xsl:template match="map/domain/instance" name="walker"> 
     <xsl:param name="path" select="@xpath"/> 
     <xsl:param name="context" 
       select="document('')/*/xsl:variable[@name='document']"/> 
     <xsl:choose> 
      <xsl:when test="contains($path,'/')"> 
       <xsl:call-template name="walker"> 
        <xsl:with-param name="path" 
           select="substring-after($path,'/')"/> 
        <xsl:with-param name="context" 
         select="$context/*[name()=substring-before($path,'/')]"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:when test="starts-with($path,'@')"> 
       <xsl:value-of select="concat(
             string-length(
              $context/attribute::* 
              [name()=substring($path,2)]) 
             [email protected], 
             '&#xA;')"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="concat(
             string-length(
              $context/*[name()=$path]) 
             [email protected], 
             '&#xA;')"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

Выход:

false 
true 

Редактировать: 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" 
xmlns:my="example.org"> 
    <xsl:output method="text"/> 
    <xsl:strip-space elements="*"/> 
    <xsl:variable name="document"> 
     <root> 
      <sub> 
       <element1 value="abc"/> 
       <element2 value="123"/> 
      </sub> 
      <sub1> 
       <element1 value="ert"/> 
       <element2 value="abc"/> 
      </sub1> 
     </root> 
    </xsl:variable> 
    <xsl:template match="map/domain/instance"> 
     <xsl:sequence select="my:xpath(@xpath,$document) 
            /string(string-length() = 
              current()/@length)"/> 
     <xsl:text>&#xA;</xsl:text> 
    </xsl:template> 
    <xsl:function name="my:xpath" as="item()*"> 
     <xsl:param name="path" as="xs:string"/> 
     <xsl:param name="context" as="node()*"/> 
     <xsl:variable name="steps" as="item()*" 
         select="tokenize($path,'/')"/> 
     <xsl:variable name="this" as="item()*" 
         select="$context/(*[if ($steps[1]='*') 
              then true() 
              else name()=$steps[1]]| 
             @*[if ($steps[1]='@*') 
              then true() 
              else name() = 
               substring($steps[1],2)])"/> 
     <xsl:choose> 
      <xsl:when test="count($steps)>1"> 
       <xsl:sequence 
        select="my:xpath(string-join($steps[position()!=1], 
               '/'), 
            $this)"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:sequence select="$this"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:function> 
</xsl:stylesheet> 

Выход:

false 
true 

Edit 2: Немного improven. Так что теперь, с этим входом:

<map> 
    <domain> 
     <instance xpath="root/sub/element1/@*" length="2"/> 
    </domain> 
    <domain> 
     <instance xpath="root/sub/*/@value" length="3"/> 
    </domain> 
</map> 

Выход:

false 
true true 
+0

Не плохо, @Alejandro! (+1) .A –

+0

@ Dimitre: Спасибо! Я немного сражался с типом '$ document' ... – 2010-08-26 13:04:36