从外部文件

时间:2016-03-07 04:16:25

标签: xml xslt xslt-2.0

请建议如何根据外部文件根据其中给出的xpath更新元素的名称。

我试过,几乎没有变量来存储来自外部文件的xpath,模板匹配元素的xpath,但是无法获得所需的信息。请建议。

外部文件(FindReplaceElements.ini):

<root>
<tofind>aside/p</tofind>    <toreplace><p class="aside_Para"></p></toreplace>
<tofind>aside[@class="sidenote1"]/p</tofind>    <toreplace><p class="aside_Para1"></p></toreplace>
<tofind>body/p</tofind>    <toreplace><p class="body_Para"></p></toreplace>
<tofind>body/div/div/h1</tofind>    <toreplace><p class="body_h_2"></p></toreplace>
<tofind>body/div/div/div/h1</tofind>    <toreplace><p class="body_h_3"></p></toreplace>
</root>

输入XML:

<article>
<body>
    <p>The body para1</p>
    <aside><p>Aside para1</p></aside>
    <aside class="sidenote1"><p>Aside para2</p></aside>
    <div><div class="special"><h1>The Heading1</h1></div></div>
    <div><div><div><h1>The Heading2</h1></div></div></div>
</body>
</article>

必填结果:

<article>
<body>
    <p class="body_Para">The body para1</p>
    <aside><p class="aside_Para">Aside para1</p></aside>
    <aside class="sidenote1"><p class="aside_Para1">Aside para2</p></aside>
    <div><div class="special"><p class="body_h_2">The Heading1</p></div></div>
    <div><div><div><p class="body_h_3">The Heading2</p></div></div></div>
</body>
</article>

XSLT:

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

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

<xsl:variable name="varDocElemsIni" select="document('FindReplaceElements.ini')"/>
<xsl:variable name="varDQote">"</xsl:variable>

<xsl:template match="p">
    <xsl:variable name="nodeAsStr"><xsl:value-of select="name(.)"/></xsl:variable><!--String name of element -->
    <xsl:variable name="varAllMatchedEles">            <!--getting Elements name from INI file-->
        <xsl:for-each select="$varDocElemsIni/root/tofind">
            <xsl:variable name="varNextElemINI"><xsl:value-of select="following-sibling::*[1]/name()"/></xsl:variable><!--From INI file, required element name-->
            <xsl:variable name="varPathINI"><!--xPath of element from INI file-->
            <xsl:for-each select="$varDocElemsIni/root/tofind/tokenize(text(), '/')[not(position()=last())]">
                <xsl:value-of select="."/><xsl:value-of select="'/'"/>
            </xsl:for-each>
        </xsl:variable>
            <xsl:variable name="varNameElem1">
                <xsl:for-each select="tokenize(text(), '/')[last()]">
                    <xsl:if test=". = $nodeAsStr">
                        <xsl:value-of select="$varNextElemINI"/>
                    </xsl:if>
                </xsl:for-each>
            </xsl:variable>
        </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="varPath"><!--xPath of Element from given input file -->
        <xsl:value-of select="concat(ancestor::*[2]/name(), '/', parent::*/name())"/>
    </xsl:variable>

    <xsl:choose>
        <xsl:when test="$varAllMatchedEles=$varPath">
            <xsl:element name="{$varNextElemINI}"><xsl:apply-templates select="@*|node()"/></xsl:element>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
        </xsl:otherwise>
    </xsl:choose>

</xsl:template>
</xsl:stylesheet>

另外一个XSLT尝试如下:但无法获得结果

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

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

<xsl:variable name="varDocElemsIni" select="document('FindReplaceElements.ini')"/>
<xsl:variable name="vardQote">"</xsl:variable>
<xsl:template match="h1">
    <xsl:call-template name="TempInsertElemsAttribs"/>
</xsl:template>

<xsl:template match="h2">
    <xsl:call-template name="TempInsertElemsAttribs"/>
</xsl:template>

<xsl:template name="TempInsertElemsAttribs">
    <xsl:variable name="varReqElemName">
        <xsl:for-each select="$varDocElemsIni/root/tofind/*[name()=current()/name()]">
            <xsl:value-of select="parent::tofind/following-sibling::*[1][name()='toreplace']/child::*/name()"/>
        </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="varReqElemNameAttrib">
        <xsl:for-each select="$varDocElemsIni/root/tofind/*[name()=current()/name()]/parent::tofind/following-sibling::*[1][name()='toreplace']/child::*/@*">
            <xsl:value-of select="concat(name(), '=', $vardQote, ., $vardQote)"/><xsl:if test="not(position()=last())"><xsl:text> </xsl:text></xsl:if>
        </xsl:for-each>
    </xsl:variable>

    <xsl:choose>
        <xsl:when test="string-length($varReqElemName) gt 0">
            <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="$varReqElemName"/>
                <xsl:if test="string-length($varReqElemNameAttrib) gt 0"><xsl:value-of select="concat(' ', $varReqElemNameAttrib)"/></xsl:if>
            <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
                <xsl:apply-templates/>
            <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="$varReqElemName"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>    
</xsl:stylesheet> 

1 个答案:

答案 0 :(得分:2)

我建议你分两步完成:

首先,将以下样式表应用于&#34;外部文件&#34;:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

<xsl:template match="/root">
    <axsl:stylesheet version="2.0">
        <axsl:template match="@*|node()">
            <axsl:copy>
                <axsl:apply-templates select="@*|node()"/>
            </axsl:copy>
        </axsl:template>
        <xsl:apply-templates select="tofind"/>
    </axsl:stylesheet>
</xsl:template>

<xsl:template match="tofind">
    <axsl:template match="{.}">
        <xsl:apply-templates select="following-sibling::toreplace[1]/*"/>
    </axsl:template>
</xsl:template>

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

</xsl:stylesheet>

您的示例中的结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="aside/p">
      <p class="aside_Para">
         <xsl:apply-templates select="@*|node()"/>
      </p>
   </xsl:template>
   <xsl:template match="aside[@class=&#34;sidenote1&#34;]/p">
      <p class="aside_Para1">
         <xsl:apply-templates select="@*|node()"/>
      </p>
   </xsl:template>
   <xsl:template match="body/p">
      <p class="body_Para">
         <xsl:apply-templates select="@*|node()"/>
      </p>
   </xsl:template>
   <xsl:template match="body/div/div/h1">
      <p class="body_h_2">
         <xsl:apply-templates select="@*|node()"/>
      </p>
   </xsl:template>
   <xsl:template match="body/div/div/div/h1">
      <p class="body_h_3">
         <xsl:apply-templates select="@*|node()"/>
      </p>
   </xsl:template>
</xsl:stylesheet>

这个结果是一个自己的XSLT样式表。应用它您的输入示例将产生以下结果:

<?xml version="1.0" encoding="UTF-8"?><article>
<body>
    <p class="body_Para">The body para1</p>
    <aside><p class="aside_Para">Aside para1</p></aside>
    <aside class="sidenote1"><p class="aside_Para1">Aside para2</p></aside>
    <div><div class="special"><p class="body_h_2">The Heading1</p></div></div>
    <div><div><div><p class="body_h_3">The Heading2</p></div></div></div>
</body>
</article>

请注意,其中一些规则含糊不清。当您将生成XSLT的过程分配给外部代理时,您可能会遇到危险。