[英]xsltproc merging xml files not working
嗨,我必須在以下條件下合並xml文件:
復制新文件的所有現有節點,然后與舊文件值合並。 例如:
文件abc.xml
<?xml version="1.0"?>
<schedule>
<Item Id="2">
<measurements>
<measurement>Alpha</measurement>
</measurements>
</Item>
<Item Id="9">
<measurements>
<measurement>Gamma</measurement>
</measurements>
</Item>
</schedule>
文件xyz.xml
<?xml version="1.0"?>
<schedule>
<Item Id="1">
<measurements>
<measurement>Alpha</measurement>
</measurements>
</Item>
<Item Id="4">
<measurements>
<measurement>Beta</measurement>
</measurements>
</Item>
</schedule>
xslt邏輯文件:logic.xslt
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="no" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Item">
<xsl:variable name="match" select="document('./abc.xml')/schedule/Item[measurements/measurement=current()/measurements/measurement]"/>
<xsl:choose>
<xsl:when test="$match">
<xsl:copy-of select="$match"/>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
使用的命令:
xsltproc logic.xslt xyz.xml > output.xml
預期產量:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<schedule>
<Item Id="2">
<measurements>
<measurement>Alpha</measurement>
</measurements>
</Item>
<Item Id="4">
<measurements>
<measurement>Beta</measurement>
</measurements>
</Item>
<Item Id="9">
<measurements>
<measurement>Gamma</measurement>
</measurements>
</Item>
</schedule>
但是實際不同於預期的如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<schedule>
<Item Id="2">
<measurements>
<measurement>Alpha</measurement>
</measurements>
</Item>
<Item Id="9">
<measurements>
<measurement>Gamma</measurement>
</measurements>
</Item>
</schedule>
它錯過了新xml文件中的節點。
更改
<xsl:choose>
<xsl:when test="$match">
<xsl:copy-of select="$match"/>
</xsl:when>
</xsl:choose>
至
<xsl:choose>
<xsl:when test="$match">
<xsl:copy-of select="$match"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:choose>
通過編輯問題和需要復制第二個文檔中的其他元素,我認為問題更加棘手,使用XSLT 3,您可以像在https://xsltfiddle.liberty-development.net/pPqsHTf中那樣進行操作
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:param name="doc1" select="/"/>
<xsl:param name="doc2">
<schedule>
<Item Id="2">
<measurements>
<measurement>Alpha</measurement>
</measurements>
</Item>
<Item Id="9">
<measurements>
<measurement>Gamma</measurement>
</measurements>
</Item>
</schedule>
</xsl:param>
<xsl:key name="ref" match="Item" use="measurements/measurement"/>
<xsl:template match="schedule">
<xsl:copy>
<xsl:apply-templates select="Item, $doc2/schedule/Item[not(key('ref', measurements/measurement, $doc1))]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Item[root() is $doc1 and key('ref', measurements/measurement, $doc2)]">
<xsl:copy-of select="key('ref', measurements/measurement, $doc2)"/>
</xsl:template>
</xsl:stylesheet>
(當然,不用內聯第二個文檔,您可以使用<xsl:param name="doc2" select="document('abc.xml')"/>
),但是對於XSLT 1,使用變量和鍵,您不能在匹配模式中使用它們,因此似乎需要一種方法,如https://xsltfiddle.liberty-development.net/pPqsHTf/2
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:param name="doc1" select="/"/>
<xsl:param name="doc2-rtf">
<schedule>
<Item Id="2">
<measurements>
<measurement>Alpha</measurement>
</measurements>
</Item>
<Item Id="9">
<measurements>
<measurement>Gamma</measurement>
</measurements>
</Item>
</schedule>
</xsl:param>
<xsl:param name="doc2" select="exsl:node-set($doc2-rtf)" xmlns:exsl="http://exslt.org/common"/>
<xsl:template match="schedule">
<xsl:copy>
<xsl:apply-templates select="Item"/>
<xsl:copy-of select="$doc2/schedule/Item[not(measurements/measurement = $doc1//Item/measurements/measurement)]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Item">
<xsl:choose>
<xsl:when test="measurements/measurement = $doc2//Item/measurements/measurement">
<xsl:copy-of select="$doc2//Item[measurements/measurement = current()/measurements/measurement]"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
當然,再次簡單地使用<xsl:param name="doc2" select="document('abc.xml')"/>
而不是使用數據內聯(我只是做一個完整的示例,不幸的是使用XSLT 1然后需要使用節點集擴展功能)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.