如何在多个节点中使用 XLS 修改 XML 中带有子字符串的元素的属性值

How to revise element's attribute values with substring in XML with XLS in multiple nodes

我正在尝试更改此 XML 示例

中所有节点中的类别“名称”值
<?xml version="1.0" encoding="utf-8"?>
<offer xmlns:iof="********" xmlns:iaiext="******" file_format="IOF" generated="***" expires="***" version="3.0" extensions="yes">
  <products currency="EUR" iof_translation_generated="no" language="eng">
    <product id="170" currency="EUR" code_on_card="******" producer_code_standard="GTIN13" type="regular" vat="23.0" site="1">
      <producer id="1404978613" name="Test"/>
      <category id="1214554589" name="Cell phone screwdrivers"/>
      <category_idosell id="2898" path="Hardware &gt; Tools"/>
      <unit id="0" name="pc."/>
      <warranty id="2" type="seller" period="12" name="Cell phone accessories"/>
      <price gross="1.1" net="0.9"/>
    </product>
    <product id="411" currency="EUR" code_on_card="******" producer_code_standard="OTHER" type="regular" vat="23.0" site="1">
      <producer id="1404978613" name="Test"/>
      <category id="1214554594" name="Service Tools"/>
      <category_idosell id="2898" path="Hardware &gt; Tools"/>
      <unit id="0" name="pc."/>
      <warranty id="1" type="seller" period="6" name="Cell phone spare parts"/>
      <price gross="10.84" net="8.82"/>
    </product>
</products>
</offer>

使用此 XSL 片段:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
  
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="category/@name">
   
        <xsl:element name="category">
            <xsl:attribute name="name">
                <xsl:value-of select="substring-before(//category_idosell[1]/@path, ' &gt; ')"/>
                <xsl:value-of select="'///'"/>
                <xsl:value-of select="substring-after(//category_idosell[1]/@path, ' &gt; ')"/>
                <xsl:value-of select="'///'"/>
                <xsl:value-of select="//category[1]/@name"/>
            </xsl:attribute>
        </xsl:element>
    </xsl:template>
    
</xsl:stylesheet>

当我在单个节点中使用它时它可以工作,但是当我有更多节点(产品)时它会给我这个错误:

A sequence of more than one item is not allowed as the first argument of fn:substring-before() ("Hardware > Tools", "Hardware > Tools")

有人可以帮助我解决我遗漏的问题以及如何让它发挥作用吗? 提前谢谢你

在模板内部,例如xsl:template match="category/@name" 上下文节点发生变化,在您的情况下是 name 属性节点,因此您想编写相对于该节点的路径表达式,例如 ../../category_idosell[1]/@path 而不是以 // 开头的绝对路径搜索整个文档。基于此以及您的代码试图创建一个元素而您似乎只想更改属性节点的值的出色评论我认为您想要一些类似于

的东西
  <xsl:template match="category/@name">
      <xsl:attribute name="{name()}"
        select="concat(substring-before(../../category_idosell[1]/@path, ' &gt; '), '///',substring-after(../../category_idosell[1]/@path, ' &gt; '),'///', .)"/>
  </xsl:template>

你还没有说你想要什么输出,所以很难更正你的代码。

如果您想从文档中的第一个产品中获取值,请使用

(//category_idosell)[1]

如果要从当前产品中获取值,请使用

../category_idosell

您的示例有点模棱两可,因为两种产品在 category_idosell/@path 中具有相同的值。 AFAICT,你想做的很简单:

<xsl:template match="category/@name">
    <xsl:attribute name="name">
        <xsl:value-of select="substring-before(../../category_idosell/@path, ' &gt; ')"/>
        <xsl:text>///</xsl:text>
        <xsl:value-of select="substring-after(../../category_idosell/@path, ' &gt; ')"/>
        <xsl:text>///</xsl:text>
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

或者更简单:

<xsl:template match="category/@name">
    <xsl:attribute name="name">
        <xsl:value-of select="replace(../../category_idosell/@path, ' &gt; ', '///')"/>
        <xsl:text>///</xsl:text>
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>