【问题标题】:Replace attribute values of a xml file according to a ID value using XSLT 1.0使用 XSLT 1.0 根据 ID 值替换 xml 文件的属性值
【发布时间】:2012-08-03 03:38:35
【问题描述】:

我有一个这样的主要 XML 文档:

<chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter1">
<title>First chapter</title>
      <section xml:id="section1">
                <imageobject>
                    <id>aa12</id>
                    <image fileref="image1.jpg"/>
                </imageobject>
                <imageobject>
                    <id>bb13</id>
                    <image fileref="image2.jpg"/>
                </imageobject>
      </section>
      <section xml:id="section2" xml:base="../other/section1.xml">  
                    <imageobject>
                        <id>ab14</id>
                        <image fileref="image1.jpg"/>
                    </imageobject>
                    <imageobject>
                        <id>ab15</id>
                        <image fileref="image2.jpg"/>
                    </imageobject>

             <section xml:id="section3" xml:base="../some-other/more/section3.xml">
                    <imageobject>
                        <id>ac16</id>
                        <image fileref="image1.jpg"/>
                    </imageobject>
             </section>
    </section>
    <section xml:id="section4" xml:base="../some-other/section4.xml">
                    <imageobject>
                        <id>ac17</id>
                        <image fileref="image2.jpg"/>
                    </imageobject>
    </section>
 </chapter>

还有另一个 XML 文件和值,例如:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <NewData>
       <Rename id="ab14" imageName="aaaa.jpg"/>
       <Rename id="ab15" imageName="bbbb.jpg"/>
       <Rename id="ac16" imageName="cccc.jpg"/>
       <Rename id="ac17" imageName="dddd.jpg"/>
    </NewData>

最后我需要一个类似下面的输出,根据 id 值替换为正确的重命名图像名称。

<chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter1">
    <title>First chapter</title>
    <section xml:id="section1">
                    <imageobject>
                        <image fileref="image1.jpg"/>
                    </imageobject>
                    <imageobject>
                        <image fileref="image2.jpg"/>
                    </imageobject>
    </section>
    <section xml:id="section2" xml:base="../other/section1.xml">  
                        <imageobject>
                            <image fileref="aaaa.jpg"/>
                        </imageobject>
                        <imageobject>
                            <image fileref="bbbb.jpg"/>
                        </imageobject>

             <section xml:id="section3" xml:base="../some-other/more/section3.xml">
                        <imageobject>
                            <image fileref="cccc.jpg"/>
                        </imageobject>
             </section>
   </section>
   <section xml:id="section4" xml:base="../some-other/section4.xml">
                        <imageobject>
                            <image fileref="dddd.jpg"/>
                        </imageobject>
   </section>
</chapter>

这里发生的情况是:如果第一个 XML 文档中的 id 属性与第二个 XML 中的 id 属性匹配,那么第一个文档中的 fileref 的值将被匹配的 imageName 替换第二个 XML 文件。

请看我在这里给出的例子。

如何使用 XSLT 1.0 做到这一点?

我正在使用 Saxon 或 Xsltproc 处理器。

提前谢谢..!!

【问题讨论】:

    标签: xml xslt xpath xslt-1.0


    【解决方案1】:

    这是一个 XSLT 1.0 样式表(使用 xsltproc 和 Saxon 6 都支持的 exsl:node-set):

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:exsl="http://exslt.org/common"
      exclude-result-prefixes="exsl">
    
    <xsl:param name="doc2-url" select="'test2012080602.xml'"/>
    <xsl:variable name="doc2" select="document($doc2-url)"/>
    
    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>
    
    <xsl:key name="img-by-id" match="Rename" use="@id"/>
    
    <xsl:template match="@* | node()">
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
    </xsl:template>
    
    <xsl:template match="imageobject">
       <xsl:copy>
         <xsl:variable name="id" select="id"/>
         <xsl:variable name="ref">
           <xsl:for-each select="$doc2">
             <xsl:if test="key('img-by-id', $id)">
               <image filref="{key('img-by-id', $id)/@imageName}"/>
             </xsl:if>
           </xsl:for-each>
         </xsl:variable>
         <xsl:variable name="new" select="exsl:node-set($ref)/image"/>
         <xsl:choose>
           <xsl:when test="$new">
             <xsl:copy-of select="$new"/>
           </xsl:when>
           <xsl:otherwise>
             <xsl:copy-of select="image"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>
    

    您可以将参数doc2-url 设置为具有新名称的辅助输入文档的位置。

    【讨论】:

    • 哇..!! =D 效果很好..非常感谢马丁..你太棒了..
    • Martin,我看不到这里使用了 ext:node-set() ——也许你需要编辑答案并删除提及 EXSLT——以及代码中的命名空间声明?
    • Dimitre,我不明白您在评论中要问什么。 &lt;xsl:variable name="new" select="exsl:node-set($ref)/image"/&gt; 在样式表示例中对您不可见吗?我可以理解 cmets 是否有必要使用 exsl:node-set 来解决问题,但我想我这些天在 XSLT 2.0 方面想得太多了,就像使用和访问带有 XPath 的临时树一样,我更喜欢使用这种方式exsl:node-set 在 XSLT 1.0 中(如果可用)。
    猜你喜欢
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-12
    • 2022-01-26
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    相关资源
    最近更新 更多