【问题标题】:Combine xlst transformations into one将 xlst 转换合并为一个
【发布时间】:2017-05-25 05:30:20
【问题描述】:

我有一些用于修改 xml 文档的 xslt 文件。 ArcGIS Desktop 10.4 的元数据 xml。目前我将它们链接在一起以获得所需的输出xml(将xslt 1应用于输入xml,然后将xslt 2应用于第一步的输出,然后应用xslt 3)。虽然这很好用,但我想将我的三张纸合二为一。我已经尝试过,但是当我组合它们时,每个部分都会“覆盖”最后一个。

这会删除所有不需要的节点。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="no" />
   <!-- process the metadata using the templates below -->
   <xsl:template match="/">
      <xsl:apply-templates select="node() | @*" />
   </xsl:template>
   <!-- copy all metadata conent -->
   <xsl:template match="node() | @*" priority="0">
      <xsl:copy>
         <xsl:apply-templates select="node() | @*" />
      </xsl:copy>
   </xsl:template>
   <!--  If the element exists, remove it -->
   <xsl:template match="resConst | Process | mdContact | citRespParty | idPoC | idCredit | prcStep | rpIndName | rpOrgName | rpPosName | role | displayName | rpCntInfo | searchKeys | themeKeys" />
</xsl:stylesheet>

这增加了一些使用限制。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="no" />
   <!-- process the metadata using the templates below -->
   <xsl:template match="/">
      <xsl:apply-templates select="node() | @*" />
   </xsl:template>
   <!-- copy all metadata conent -->
   <xsl:template match="node() | @*" priority="0">
      <xsl:copy>
         <xsl:apply-templates select="node() | @*" />
      </xsl:copy>
   </xsl:template>
   <!-- Add Nodes -->
   <xsl:template match="dataIdInfo">
      <xsl:copy>
         <xsl:copy-of select="node() | @*" />
         <resConst>
            <Consts>
               <useLimit>CONFIDENTIAL AND PROPRIETARY INFORMATION</useLimit>
            </Consts>
         </resConst>
         <searchKeys>
            <keyword>keyword</keyword>
         </searchKeys>
         <themeKeys>
            <keyword>keyword</keyword>
         </themeKeys>
    <idCredit>our org</idCredit>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

最后,这个增加了一个联系点。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="no" />
   <!-- process the metadata using the templates below -->
   <xsl:template match="/">
      <xsl:apply-templates select="node() | @*" />
   </xsl:template>
   <!-- copy all metadata conent -->
   <xsl:template match="node() | @*" priority="0">
      <xsl:copy>
         <xsl:apply-templates select="node() | @*" />
      </xsl:copy>
   </xsl:template>
   <!-- Add Nodes -->
   <xsl:template match="idCitation">
      <xsl:copy>
      <xsl:copy-of select="node() | @*" />
         <citRespParty>
            <rpIndName>name</rpIndName>
            <rpOrgName>org</rpOrgName>
            <rpPosName>role</rpPosName>
            <role>
               <RoleCd value="007" />
            </role>
            <rpCntInfo>
               <cntAddress addressType="">
                  <delPoint>street number</delPoint>
                  <city>city</city>
                  <adminArea>state</adminArea>
                  <postCode>zip</postCode>
                  <eMailAdd>email</eMailAdd>
                  <country>country</country>
               </cntAddress>
               <cntPhone>
                  <voiceNum tddtty="">phone number</voiceNum>
               </cntPhone>
            </rpCntInfo>
         </citRespParty>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

示例输入: http://textuploader.com/d92rd

示例输出: http://textuploader.com/d92r6

示例节点更改:您将看到 resConsts 是节点被完全删除。然后在与我们的组织使用限制文本相同的 XPath 中添加一个新的 resConsts 节点。

这是基于我的流程的 Esri 站点: http://desktop.arcgis.com/en/arcmap/10.3/manage-data/metadata/editing-metadata-for-many-arcgis-items.htm

【问题讨论】:

  • 您确定这是个好主意吗?做相反的事情通常被认为是一种好的做法:将复杂的转换分解为由单独、简单、可重用的步骤组成的管道。
  • 不,我不确定这是个好主意。我以前从未使用过 xslt。我在想将它们结合起来会更有效/更专业。现在我用 python 把它们锁起来了。

标签: xml xslt


【解决方案1】:

我已经尝试过,但是当我组合它们时,每个部分都会“覆盖”最后一个。

没有看到输入示例,我们只能猜测为什么会发生这种情况。我的猜测是您正在使用一些模板来 复制 节点,您应该将其他模板应用到这些节点上。复制节点会将其直接写入结果树 - 其他模板无法访问。

如果我的猜测是正确的,那么你只需要更改所有出现的:

<xsl:copy-of select="node() | @*" />

到:

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

XSLT

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<!--  remove selected elements (and their descendants) -->
<xsl:template match="resConst | Process | mdContact | citRespParty | idPoC | idCredit | prcStep | rpIndName | rpOrgName | rpPosName | role | displayName | rpCntInfo | searchKeys | themeKeys" />

<!-- add nodes to dataIdInfo -->
<xsl:template match="dataIdInfo">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" />
        <resConst>
            <Consts>
                <useLimit>CONFIDENTIAL AND PROPRIETARY INFORMATION</useLimit>
            </Consts>
        </resConst>
        <searchKeys>
            <keyword>keyword</keyword>
        </searchKeys>
        <themeKeys>
            <keyword>keyword</keyword>
        </themeKeys>
        <idCredit>our org</idCredit>
    </xsl:copy>
</xsl:template>

<!-- add nodes to idCitation -->
<xsl:template match="idCitation">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" />
        <citRespParty>
            <rpIndName>name</rpIndName>
            <rpOrgName>org</rpOrgName>
            <rpPosName>role</rpPosName>
            <role>
                <RoleCd value="007" />
            </role>
            <rpCntInfo>
                <cntAddress addressType="">
                    <delPoint>street number</delPoint>
                    <city>city</city>
                    <adminArea>state</adminArea>
                    <postCode>zip</postCode>
                    <eMailAdd>email</eMailAdd>
                    <country>country</country>
                </cntAddress>
                <cntPhone>
                    <voiceNum tddtty="">phone number</voiceNum>
                </cntPhone>
            </rpCntInfo>
        </citRespParty>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

【讨论】:

  • 对不起,我添加了一个非常精简的输入 xml。是的,我正在尝试复制所有节点。然后我需要删除一些节点,然后添加一些新节点。有时,在删除节点之前,添加的节点可能已经存在。
  • 请同时添加预期结果并解释它与建议样式表产生的结果有何不同。
  • "有时在删除节点之前添加的节点可能已经存在。" 恐怕我不明白你的意思。
  • 已将输入和输出文件上传到文本主机。恐怕他们的帖子太多了。我还概述了如何更改一个节点。 resConst 在第一个 xslt 中被删除,然后在第 2 步 xslt 中重新添加。
  • 恐怕我听不懂你在说什么。而且我没有时间在所有这些中寻找差异。请查明问题 - 如果存在。 AFAICT,应该删除现有的 resConst 并添加一个新的 resConst 元素 - 这正是我的样式表所做的。
【解决方案2】:

考虑使用XProc

<p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
    xmlns:c="http://www.w3.org/ns/xproc-step" version="1.0">
    <p:input port="source">
        <p:document href="input-file.xml"></p:document>
    </p:input>
    <p:output port="result"/>
    <p:xslt>
        <p:input port="stylesheet">
            <p:document href="sheet1.xsl"/>
        </p:input>
        <p:input port="parameters">
            <p:empty/>
        </p:input>
    </p:xslt>
    <p:xslt>
        <p:input port="stylesheet">
            <p:document href="sheet2.xsl"/>
        </p:input>
        <p:input port="parameters">
            <p:empty/>
        </p:input>
    </p:xslt>
    <p:xslt>
        <p:input port="stylesheet">
            <p:document href="sheet3.xsl"/>
        </p:input>
        <p:input port="parameters">
            <p:empty/>
        </p:input>
    </p:xslt>

</p:declare-step>

或某些特定于处理器的链接(http://saxonica.com/html/documentation/extensions/output-extras/serialization-parameters.htmlsaxon:next-in-chain)。

如果您想手动将三个样式表合并为一个样式表,请了解如何使用 modes 并进行设置:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

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

<xsl:template match="resConst | Process | mdContact | citRespParty | idPoC | idCredit | prcStep | rpIndName | rpOrgName | rpPosName | role | displayName | rpCntInfo | searchKeys | themeKeys" 
 mode="step1"/>

   <xsl:template match="dataIdInfo" mode="step2">
      <xsl:copy>
         <xsl:copy-of select="node() | @*" />
         <resConst>
            <Consts>
               <useLimit>CONFIDENTIAL AND PROPRIETARY INFORMATION</useLimit>
            </Consts>
         </resConst>
         <searchKeys>
            <keyword>keyword</keyword>
         </searchKeys>
         <themeKeys>
            <keyword>keyword</keyword>
         </themeKeys>
    <idCredit>our org</idCredit>
      </xsl:copy>
   </xsl:template>

<xsl:variable name="step1">
  <xsl:apply-templates mode="step1"/>
</xsl:variable>

<xsl:variable name="step2">
  <xsl:apply-templates select="$step1/node()" mode="step2"/>
</xsl:variable>

<xsl:template match="/">
  <xsl:apply-templates select="$step2/node()"/>
</xsl:template>

   <xsl:template match="idCitation">
      <xsl:copy>
      <xsl:copy-of select="node() | @*" />
         <citRespParty>
            <rpIndName>name</rpIndName>
            <rpOrgName>org</rpOrgName>
            <rpPosName>role</rpPosName>
            <role>
               <RoleCd value="007" />
            </role>
            <rpCntInfo>
               <cntAddress addressType="">
                  <delPoint>street number</delPoint>
                  <city>city</city>
                  <adminArea>state</adminArea>
                  <postCode>zip</postCode>
                  <eMailAdd>email</eMailAdd>
                  <country>country</country>
               </cntAddress>
               <cntPhone>
                  <voiceNum tddtty="">phone number</voiceNum>
               </cntPhone>
            </rpCntInfo>
         </citRespParty>
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

在浏览器中输入,未经测试,但应该显示原理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    相关资源
    最近更新 更多