所以我有一个XML文件,格式如下:
[...]
<level1>
<para id="1"/>
<image type="photo" artist="Joe"/>
<para id="2"/>
<para id="3"/>
<level2>
<para id="4"/>
<image type="pencil" artist="Bob"/>
<para id="5"/>
</level2>
<para id="6"/>
<image type="oil" artist="Joe"/>
</level1>
[...]
问题在于图像属性并不总是正确的,并且它们没有唯一的标识符。我有另一个具有所有正确属性的文件。我试图编写一个将删除不正确属性的转换,然后从我的其他文件中放入正确的属性。
这是我到目前为止所拥有的:
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- ============================================================= -->
<xsl:variable name="target" select="document('correct.xml')//image"/>
<xsl:template match="image">
<xsl:variable name="vPath1">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/',name())"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="vPath2">
<xsl:for-each select="$target[ancestor-or-self::*]">
<xsl:value-of select="concat('/',name())"/>
</xsl:for-each>
</xsl:variable>
<xsl:copy>
<xsl:if test="$vPath1=$vPath2">
<xsl:copy-of select="$target/@*"/>
</xsl:if>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
这成功删除了所有不正确的属性,但它没有放置正确的属性。看起来像我的&#39; if&#39;声明永远不会打,但我知道路径是一样的。我做错了什么?
我的correct.xml看起来像这样(输出应该是这样的):
[...]
<level1>
<para id="1"/>
<image type="pencil" artist="Joe"/>
<para id="2"/>
<para id="3"/>
<level2>
<para id="4"/>
<image type="photo" artist="Steve"/>
<para id="5"/>
</level2>
<para id="6"/>
<image type="oil" artist="Bob"/>
</level1>
[...]
答案 0 :(得分:1)
如果2个XML文档的结构完全匹配,则可以使用位置谓词匹配路径。这将确保您比较独特的路径。
否则你必须匹配id或其他东西。如果是这种情况,请告诉我,我可以在生成路径时更新我的答案以使用id
(或其他)属性。
XML输入
<level1>
<para id="1"/>
<image type="photo" artist="Joe"/>
<para id="2"/>
<para id="3"/>
<level2>
<para id="4"/>
<image type="pencil" artist="Bob"/>
<para id="5"/>
</level2>
<para id="6"/>
<image type="oil" artist="Joe"/>
</level1>
更正XML (我将其命名为so_good.xml。)
<level1>
<para id="1"/>
<image type="pencil" artist="Joe"/>
<para id="2"/>
<para id="3"/>
<level2>
<para id="4"/>
<image type="photo" artist="Steve"/>
<para id="5"/>
</level2>
<para id="6"/>
<image type="oil" artist="Bob"/>
</level1>
XSLT 2.0 (也适用于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 indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="good" select="document('so_good.xml')"/>
<xsl:template name="getPath">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/',local-name())"/>
<!--Predicate is only output when needed.-->
<xsl:if test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]">
<xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="image">
<xsl:variable name="currPath">
<xsl:call-template name="getPath"/>
</xsl:variable>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="$good//image" mode="new-attrs">
<xsl:with-param name="currPath" select="$currPath"/>
</xsl:apply-templates>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="image" mode="new-attrs">
<xsl:param name="currPath"/>
<xsl:variable name="goodPath">
<xsl:call-template name="getPath"/>
</xsl:variable>
<xsl:if test="$currPath=$goodPath">
<xsl:copy-of select="@*"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
XML输出
<level1>
<para id="1"/>
<image type="pencil" artist="Joe"/>
<para id="2"/>
<para id="3"/>
<level2>
<para id="4"/>
<image type="photo" artist="Steve"/>
<para id="5"/>
</level2>
<para id="6"/>
<image type="oil" artist="Bob"/>
</level1>
为了帮助显示所比较的内容,您可以将此xsl:message
添加到“new-attrs”模式“图片”模板中:
<xsl:message>Comparing "<xsl:value-of select="$currPath"/>" (currPath) to "<xsl:value-of select="$goodPath"/>" (goodPath). Do they match? <xsl:value-of select="boolean($currPath=$goodPath)"/></xsl:message>
您应该看到以下消息:(对不起图像)