如何使用复杂规则的xslt翻译xml

时间:2012-05-31 05:08:51

标签: xml xslt

我有一个xml文件,想要使用复杂规则的xslt进行翻译。 源xml是这样的:

<analysis>
    <blocks>
        <block id="35" original="5,13">
            <contain>6 ,7</contain>
        </block>
        <block id="33" original="20">
            <contain>11, 8, 9, 10</contain>
        </block>
    </blocks>
    <images>
        <image id = "11">./img/a.jpg </image>
    </images>
    <lines>
        <line id="6"/>
            <char font="2">a</char>
            <char font="2">a</char>
            <char font="2">a</char>
            <char font="2">a</char>
        <line id="7"/>
            <char font="2">b</char>
            <char font="2">b</char>
            <char font="2">b</char>
            <char font="2">b</char>
        <line id="8"/>
            <char font="2">c</char>
            <char font="2">c</char>
            <char font="2">c</char>
            <char font="2">c</char>
        <line id="9"/>
            <char font="2">d</char>
            <char font="2">d</char>
            <char font="2">d</char>
            <char font="2">d</char>
        <line id="10"/>
            <char font="2">e</char>
            <char font="2">e</char>
            <char font="2">e</char>
            <char font="2">e</char>
    </lines>
</analysis>

结果xml是:

<result>
    <block id="35">
        <text>
            aaaabbbb
        </text>
    </block>
    <block id="33">
        <text>
            cccc
        </text>
        <image ref="./img/a.jpg"/>
        <text>
            ddddeeee
        </text>
    </block>
</result>

规则是: 在标签“block”下,有“contains”标志,其内容是该块引用的id集。

2 个答案:

答案 0 :(得分:1)

问题中唯一没有意义的部分是img如何在输出中的两个text元素之间结束。

这是一个XSLT 2.0示例。这不是确切的,但可能足够接近您的修改以达到您的需要。

XML输入

<analysis>
    <blocks>
        <block id="35" original="5,13">
            <contain>6 ,7</contain>
        </block>
        <block id="33" original="20">
            <contain>11, 8, 9, 10</contain>
        </block>
    </blocks>
    <images>
        <image id = "11">./img/a.jpg </image>
    </images>
    <lines>
        <line id="6"/>
            <char font="2">a</char>
            <char font="2">a</char>
            <char font="2">a</char>
            <char font="2">a</char>
        <line id="7"/>
            <char font="2">b</char>
            <char font="2">b</char>
            <char font="2">b</char>
            <char font="2">b</char>
        <line id="8"/>
            <char font="2">c</char>
            <char font="2">c</char>
            <char font="2">c</char>
            <char font="2">c</char>
        <line id="9"/>
            <char font="2">d</char>
            <char font="2">d</char>
            <char font="2">d</char>
            <char font="2">d</char>
        <line id="10"/>
            <char font="2">e</char>
            <char font="2">e</char>
            <char font="2">e</char>
            <char font="2">e</char>
    </lines>
</analysis>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <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="/">
        <results>
            <xsl:apply-templates select="analysis/blocks/block"/>
        </results>
    </xsl:template>

    <xsl:template match="block">
        <xsl:copy>
            <xsl:apply-templates select="@*[not(name()='original')]"/>
            <xsl:apply-templates select="/*/*/image[@id=tokenize(current()/contain,'\s*,\s*')]"/>
            <text>
                <xsl:apply-templates select="/*/*/line[@id=tokenize(current()/contain,'\s*,\s*')]/following-sibling::char[preceding-sibling::line[1][@id=tokenize(current()/contain,'\s*,\s*')]]/text()"/>
            </text>         
        </xsl:copy>     
    </xsl:template>

    <xsl:template match="image">
        <image ref="{normalize-space(.)}"/>
    </xsl:template>

</xsl:stylesheet>

XML输出

<results>
   <block id="35">
      <text>aaaabbbb</text>
   </block>
   <block id="33">
      <image ref="./img/a.jpg"/>
      <text>ccccddddeeee</text>
   </block>
</results>

答案 1 :(得分: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 method="xml" indent="yes" encoding="utf-8" />
<xsl:strip-space elements="text"/>
<xsl:key name="text-resource" match="line" use="normalize-space(@id)" />
<xsl:key name="image-resource" match="image" use="normalize-space(@id)" />

<xsl:template match="/">
 <result>
  <xsl:apply-templates select="analysis/blocks/block" />
 </result>
</xsl:template>

<xsl:template match="block">
  <block id="{@id}">
  <xsl:variable name="block" select="." />

  <xsl:variable name="block-texts" as="xs:string+">
    <xsl:for-each select="tokenize(contain/text(),'\s?,\s?')" >
     <xsl:variable name="id" select="." />
     <xsl:for-each select="$block" >
      <xsl:sequence select="key('text-resource',$id)/following-sibling::char[preceding-sibling::line[1][@id=$id]]" />
     </xsl:for-each>
    </xsl:for-each>
  </xsl:variable>

  <xsl:if test="count( $block-texts) != 0" >
   <text>
    <xsl:for-each select="$block-texts" >
     <xsl:value-of select="." />
    </xsl:for-each>
   </text>
  </xsl:if>

    <xsl:for-each select="tokenize(contain/text(),'\s?,\s?')" >
     <xsl:variable name="id" select="." />
     <xsl:for-each select="$block" >
      <xsl:for-each select="key('image-resource',$id)" >
       <image href="{.}" />
      </xsl:for-each>
      </xsl:for-each>
     </xsl:for-each>
  </block>
</xsl:template>

</xsl:stylesheet>

...当应用于问题中给出的输入文档时,产生...

<?xml version="1.0" encoding="utf-8"?>
<result xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <block id="35">
      <text>aaaabbbb</text>
   </block>
   <block id="33">
      <text>ccccddddeeee</text>
      <image href="./img/a.jpg "/>
   </block>
</result>

我希望你找到我最接近的解决方案。