如何使用具有复杂规则的 XSLT 来翻译 XML



我有一个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>

规则是:在标签"块"下,有"包含"标志,其内容是块引用的ID集。

问题中唯一没有意义的部分是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>

这个样式表...

<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>

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

最新更新