我有下面这样的xml文档,
<chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter1">
<title>First chapter</title>
<section xml:id="section1">
<imageobject>
<image fileref="images/image1.jpg"/>
</imageobject>
<imageobject>
<image fileref="images/image2.jpg"/>
</imageobject>
</section>
<section xml:id="section2" xml:base="../other/section1.xml">
<imageobject>
<image fileref="images/image1.jpg"/>
</imageobject>
<imageobject>
<image fileref="images/image2.jpg"/>
</imageobject>
<section xml:id="section3" xml:base="../some-other/more/section3.xml">
<imageobject>
<image fileref="images/image1.jpg"/>
</imageobject>
</section>
</section>
<section xml:id="section4" xml:base="../some-other/section4.xml">
<imageobject>
<image fileref="images/image2.jpg"/>
</imageobject>
</section>
</chapter>
由于相同的图像名称在不同的部分重复,我使用java类重命名除第一部分以外的所有图像名称。然后我可以生成一个重命名的图像名称列表。
现在我也想在上面的xml文件中反映这些更改。例如,当我在第2节中将"image1.jpg"重命名为"aaa.jpg"时,我需要通过生成一个具有新重命名图像名称的新xml来反映初始xml中的更改。
为此,我使用Ant脚本,该脚本使用XSLT1.0,并将我的第一个xml和重命名的图像列表作为输入,生成一个具有新fileref值的新xml文档。如何制作XSLT并在Ant脚本中使用它。
这是我新命名的图片列表。
<Imagedata>
<section>
<sectionID>section2</sectionID>
<relativepath>images/aaa.jpg</relativepath>
<relativepath>images/bbb.jpg</relativepath>
</section>
<section>
<sectionID>section3</sectionID>
<relativepath>images/ccc.jpg</relativepath>
</section>
<section>
<sectionID>section4</sectionID>
<relativepath>images/ddd.jpg</relativepath>
</section>
</Imagedata>
我的新的最终xml将是
<chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter1">
<title>First chapter</title>
<section xml:id="section1">
<imageobject>
<image fileref="images/image1.jpg"/>
</imageobject>
<imageobject>
<image fileref="images/image2.jpg"/>
</imageobject>
</section>
<section xml:id="section2" xml:base="../other/section1.xml">
<imageobject>
<image fileref="images/aaa.jpg"/>
</imageobject>
<imageobject>
<image fileref="images/bbb.jpg"/>
</imageobject>
<section xml:id="section3" xml:base="../some-other/more/section3.xml">
<imageobject>
<image fileref="images/ccc.jpg"/>
</imageobject>
</section>
</section>
<section xml:id="section4" xml:base="../some-other/section4.xml">
<imageobject>
<image fileref="images/ddd.jpg"/>
</imageobject>
</section>
</chapter>
谢谢。。!!
为了快速演示,我将Imagedata文档放入下面显示的样式表中的一个变量中。在实际使用中,您将传入一个参数,该参数是图像数据文档的URI,就像这样。。。
<xsl:param name="ImageDataURI" />
<xsl:variable name="ImageData" select="document($ImageDataURI)" />
除此之外,这个XSLT1.0样式表
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="ImageData">
<Imagedata>
<section>
<sectionID>section2</sectionID>
<relativepath>images/aaa.jpg</relativepath>
<relativepath>images/bbb.jpg</relativepath>
</section>
<section>
<sectionID>section3</sectionID>
<relativepath>images/ccc.jpg</relativepath>
</section>
<section>
<sectionID>section4</sectionID>
<relativepath>images/ddd.jpg</relativepath>
</section>
</Imagedata>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="image/@fileref">
<xsl:attribute name="fileref">
<xsl:value-of select="
(msxsl:node-set($ImageData)/Imagedata/section/
sectionID[.=current()/../../../self::section/@xml:id]/
following-sibling::relativepath[
count( current()/../../preceding-sibling::imageobject) + 1
] | .)[1]"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
。。。将把您提供的输入文档转换为预期的输出文档
解释
请考虑最后一个模板中表达式的值。从匹配的fileref属性开始,我们向上导航,直到到达节并获取其id。这是由表达式…给出的。。。
current()/../../../self::section/@xml:id
然后我们取我们的查找数据,找到sectionID s。这是由表达式…给出的。。。
msxsl:node-set($ImageData)/Imagedata/section/sectionID
我们需要通过节名称来交叉链接这些节。我们通过对sectionID应用谓词来实现这一点,该谓词的值必须是焦点项的section值。谓词在这里。。。
[.=current()/../../../self::section/@xml:id]
现在我们已经找到了正确的查找部分,我们需要根据文档部分中焦点项的当前位置对其进行索引。我们通过计算前面的兄弟姐妹并加一来计算我们的位置,就像这样。。。
count( current()/../../preceding-sibling::imageobject) + 1
因此,如果查找替换节点存在,则由…给出
msxsl:node-set($ImageData)/Imagedata/section/
sectionID[.=current()/../../../self::section/@xml:id]/
following-sibling::relativepath[
count( current()/../../preceding-sibling::imageobject) + 1
当需要替换时,这一切都很好,但也有没有共同响应查找的情况。在这种情况下,我们的属性需要保留其原始值。我们通过表达形式来实现这一点。。。
( $something | .)[1]
如果$something不存在(意味着它的值是空序列),那么上面的表达式只返回焦点项。如果它确实存在,那么将返回$something的第一个项目或焦点项目。通常,并集运算符连接两个序列,按文档顺序进行重复数据消除和排序。但这两个操作数来自不同的文档,因此没有进行排序或消除重复。因此,当替换节点存在时,表达式返回替换节点,如果不存在,则返回焦点项。