使用 XSL 将元素添加到 XML

Add element to XML using XSL

这是我从 Lotus Notes 数据库导出的XML:

<?xml version="1.0" encoding="UTF-8"?>
<database xmlns="http://www.lotus.com/dxl" path="CN=ATRVSIC1/OU=RVS/O=Raiffeisen Sbg.!!notesent\frzld\test.nsf" type="standard" title="test" uselz1="true" version="8.5" nourlopen="false" replicaid="C1257D2B002A37BB" requiressl="false" multilingual="false" maintainunread="true" multidbindexed="false" logtransactions="true" advancedtemplate="false" allowstoredforms="true" savelastaccessed="false" showinopendialog="true" allowsoftdeletion="false" increasemaxfields="false" allowdesignlocking="false" imageloadsdeferred="true" maintenanceversion="2.4" markmodifiedunread="true" overwritefreespace="false" singlecopytemplate="false" allowdocumentlocking="false" optimizetablebitmaps="false" usejavascriptinpages="true" allowbackgroundagents="true" allowheadlinemonitors="true" allowspecialhierarchy="true" unicodestandardsorting="false" allowexternalconnections="false" copyprofiledocswithdesign="false">
<databaseinfo dbid="C1257D2B002A37BB" diskspace="53215232" odsversion="43" percentused="11.0086976600985" numberofdocuments="52"><datamodified><datetime dst="true">20160623T092148,11+02</datetime></datamodified><designmodified><datetime dst="true">20160624T081402,68+02</datetime></designmodified></databaseinfo>
<fulltextsettings size="11670496" update="immediate" breakat="words" casesensitive="false" attachmenttype="rawtextonly" includeattachments="false" includeencryptedfields="true"><lastindexed><datetime dst="false">20160623T081159,12+00</datetime></lastindexed></fulltextsettings>
<launchsettings><noteslaunch frameset="Main" whenopened="openframeset"/></launchsettings>
<form name="DynamicFields" type="document" recalc="false" default="false" inherit="false" private="false" mailable="false" versions="none" anonymous="false" noreplace="false" storeform="false" useapplet="false" editonopen="false" inheritdoc="none" contextpane="hide" nofocusonf6="false" treatashtml="false" nofieldindex="false" publicaccess="false" readingorder="lefttoright" allowautosave="false" manualversion="false" signdocuments="false" conflictaction="createconflicts" noinitialfocus="false" designerversion="8.5.2" nofieldexchange="false" renderpassthrough="true">
<noteinfo unid="F6A625845C3510AAC1257FDB001A6F04" noteid="34e" sequence="14">
<created><datetime dst="true">20160623T064843,56+02</datetime></created>
<modified><datetime dst="true">20160624T070923,11+02</datetime></modified>
<revised><datetime dst="true">20160624T070923,10+02</datetime></revised>
<lastaccessed><datetime dst="true">20160624T070923,11+02</datetime></lastaccessed>
<addedtofile><datetime dst="true">20160623T064843,85+02</datetime></addedtofile></noteinfo>
<updatedby><name>CN=Daniel Lesiak/OU=RVS/O=Raiffeisen Sbg.</name></updatedby>
<wassignedby><name>CN=Daniel Lesiak/OU=RVS/O=Raiffeisen Sbg.</name></wassignedby>
<globals><code event="options"><lotusscript>Option Public
Use "DynamicFields"

</lotusscript></code></globals>
<actionbar align="left" bgcolor="#f0f0f0" bordercolor="black" useappletinbrowser="false" showdefaultrightclickitems="true">
<actionbuttonstyle bgcolor="#f0f0f0" textalign="left" widthtype="default" heighttype="default" margintype="default" showdropdown="false" displayborder="onmouseover" internalmargin="0"/><font color="system"/><border color="black" style="solid" width="0px 0px 1px" dropshadow="false" insidewidth="0" outsidewidth="0" dropshadowwidth="12px"/>
<action hide="" align="left" title="Speichern" showinbar="true" showinmenu="true" displaytype="button" graphicalign="left" readingorder="lefttoright" onlyiconinbar="false" publishonolelaunch="false" showinrightbuttonmenu="false"><code event="click"><formula>@Command([FileSave])</formula></code></action></actionbar>
<body><richtext>
<pardef id="1" hide="" list="none" align="left" newpage="false" spaceafter="1" linespacing="1" spacebefore="1" readingorder="lefttoright"/>
<par def="1"/>
<par def="1"><button edge="system" type="normal" width="2in" bgcolor="system" default="false" maxlines="1" wraptext="true" widthtype="maximum" readingorder="lefttoright">Create Field<code event="click"><lotusscript>Sub Click(Source As Button)
    Dim w As New NotesUIWorkspace

    Call CreateField(w.CurrentDocument.Document, "Daniel")
End Sub</lotusscript></code></button></par>
<par def="1"><field kind="editable" name="Herbert" sign="false" type="text" protected="false" allowtabout="false" defaultfocus="false" storelocally="false" showdelimiters="true" allowmultivalues="false" useappletinbrowser="false" dataconnectionfield="data" computeaftervalidation="false"/><compositedata type="98" nexttype="222" prevtype="65418" afterparcount="6" containertype="65418" afterbegincount="3" aftercontainercount="1">
Yg4BAIQAAAAAAAAAAAA=
</compositedata></par>
<par def="1"><field kind="computed" name="Sieglinde" sign="false" type="text" protected="false" allowtabout="false" defaultfocus="false" storelocally="false" showdelimiters="true" allowmultivalues="false" useappletinbrowser="false" dataconnectionfield="data" computeaftervalidation="false"><code event="defaultvalue"><formula>"Sieglinde"</formula></code></field><compositedata type="98" nexttype="222" prevtype="65418" afterparcount="6" containertype="65418" afterbegincount="3" aftercontainercount="1">
Yg4BAIQAAAAAAAAAAAA=
</compositedata></par>
<par def="1"/></richtext></body>
<item name="$$ScriptName" seal="false" sign="true" names="false" sealed="false" authors="false" readers="false" summary="false" placeholder="false"><text>DynamicFields</text></item></form>
</database>

看起来很乱,但我就是这样导出的。现在我想要做的是使用 XSL 文件在元素 "pardef" 之后添加另一个 "par" 元素。这是我的方法:

<?xml version='1.0' encoding='utf-8'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="database/form/body/richtext/pardef">
        <xsl:copy-of select="."/>
        <xsl:element name="par">
            <xsl:attribute name="def">2</xsl:attribute>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

但这似乎除了复制已经存在的 XML 之外什么也没做。我添加另一个元素的模板不适用。 为什么它不适用,我怎样才能得到我想要的结果?

这是一个名称space问题。就在 XML 的开头,您有这个...

 <database xmlns="http://www.lotus.com/dxl" 

这意味着 database 元素和所有后代元素都在此名称中 space。名称 space 中的元素,如 pardef 与不在 space 中的元素不同,即使它也称为 pardef.

要处理这个问题,您只需在 XSLT 中也声明并使用名称space。

试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:dxl="http://www.lotus.com/dxl" version="1.0">

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

    <xsl:template match="dxl:database/dxl:form/dxl:body/dxl:richtext/dxl:pardef">
        <xsl:copy-of select="."/>
        <xsl:element name="par" namespace="http://www.lotus.com/dxl">
            <xsl:attribute name="def">2</xsl:attribute>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

请注意,使用的前缀(在本例中为 dxl)并不重要。 space URI (http://www.lotus.com/dxl) 必须在 XML 和 XSLT 之间匹配。

请注意,您可以将模板匹配更改为 <xsl:template match="dxl:pardef">。您不需要指定完整路径,除非有 pardef 个元素是您不想转换的不同级别。

另请注意,您也可以将 <xsl:element name="par" namespace="http://www.lotus.com/dxl"> 更改为仅此....

<dxl:par test="2" />