【问题标题】:XSLT: How to replace some XML element names by otherXSLT:如何将某些 XML 元素名称替换为其他元素名称
【发布时间】:2017-02-22 21:36:04
【问题描述】:

例如这是我的 XML 文件:

<?xml version="1.0" encoding="UTF-8" ?>
<products>
 <product>
   <code>37</code>
   <ws_code>T37</ws_code>
   <barcode>11111111</barcode>
 </product>
</products>

我想改成这样:

<?xml version="1.0" encoding="UTF-8" ?>
<products>
 <product>
   <ProductCode>37</ProductCode>
   <ProductBarcode>11111111</ProductBarcode>
 </product>
</products>

我正在处理一个 XSLT 文件(缺少):

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

实际上,XML 文件来自服务器,我无法对此文件进行任何更改。

如何使用 XSLT 更改这些元素名称并删除一些标签,以及如何链接 XSLT 和 XML 文件?

要更改的标签名称是:

代码 --> 产品代码
ws_code --> 应该删除
条码 --> ProductBarcode

【问题讨论】:

  • 很高兴您提供了输入 XML 和您想要的输出的清晰示例。您能否也发布您迄今为止尝试过的 XSLT?
  • code--&gt;ProductCode 转换为&lt;xsl:template match="code"&gt;&lt;ProductCode&gt;&lt;xsl:apply-templates/&gt;&lt;/ProductCode&gt;&lt;/xsl:template&gt;,将ws_code 删除为&lt;xsl:template match="ws_code"/&gt;,然后添加身份转换模板并按照该方法使用其他模板实施其他必要的更改。
  • 我在问题中添加了我的 xslt 文件示例。但我不知道如何将我的 xslt 文件连接到 xml。
  • @D.Dirik "我不知道如何将我的 xslt 文件连接到 xml。" 这取决于您将使用什么来执行转换。
  • @BenL 我添加了我的 xslt 文件。

标签: xml xslt


【解决方案1】:

您的 XSLT 非常接近您想要的,只是它没有删除 ws_code 元素并且可能更简单一些。

要删除ws_code 元素,请创建一个与之匹配的模板以不执行任何操作。

鉴于您的输入 XML,您不需要匹配 product/codeproduct/barcode。只有codebarcode 会匹配这些元素。

您可以在模板匹配中使用&lt;apply-templates/&gt; 而不是&lt;xsl:apply-templates select="@*|node()"/&gt;。这将处理当前节点的所有子节点:参见Applying Template Rules

通过在标识模板中使用*|@* 而不是node()|@*,它不会匹配文本节点,因此不会输出元素之间的空格。 codebarcode 下面的文本仍然通过文本节点的 built-in Template Rule 输出。

下面的 XSLT 实现了你想要的:

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

<xsl:template match="code">
    <ProductCode>
        <xsl:apply-templates/>
    </ProductCode>
</xsl:template>

<xsl:template match="barcode">
    <ProductBarCode>
        <xsl:apply-templates/>
    </ProductBarCode>
</xsl:template>

<xsl:template match="ws_code"/>

【讨论】:

    【解决方案2】:

    将以下 XSLT-1.0 文件(我将其命名为 d.xslt)应用于您的上述输入 XML 文件(我将其命名为 d.xml(

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:strip-space elements="*" />
    
        <!-- identity template -->
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" />
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="ws_code[local-name(..) = 'product']" />
    
        <xsl:template match="product/code">
            <ProductCode><xsl:value-of select="text()" /></ProductCode>
        </xsl:template>
    
        <xsl:template match="product/barcode">
            <ProductBarcode><xsl:value-of select="text()" /></ProductBarcode>
        </xsl:template>
    
    </xsl:stylesheet>
    

    我在 Linux/Ubuntu 上使用以下命令/XSLTProcessor 对此进行了测试:

    xsltproc d.xslt d.xml | xmlindent -f -nbe
    

    结果是:

    <?xml version="1.0"?>
    <products>
        <product>
            <ProductCode>37</ProductCode>
            <ProductBarcode>11111111</ProductBarcode>
        </product>
    </products>
    

    根据需要。

    此 XSLT 代码确实将具有 product 节点作为父节点的 codebarcode 元素分别替换为 ProductCodeProductBarcode 元素。 ws_code 节点被忽略,被忽略的 空格&lt;xsl:strip-space...&gt; 消除。

    【讨论】:

    • 我认为没有必要通过引用父级来限制匹配。而且我当然认为没有必要如此间接地提及父级:如果您真的只想匹配父级为productcode,请说product/codecode[parent::product]
    • @michael.hor257k:我根据您的一个建议更改了答案,但是,有很多方法可以通向罗马。
    • 但有些方法是不好的做法。没有理由通过其本地名称来引用元素,除非您不知道它在哪个命名空间中。这是极其罕见的——当它发生时,你就有可能从另一个具有相同本地名称但在另一个命名空间中的元素获得误报。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多