xml - xsl/xpath 选择最多的 sibling ,但不选择下一个相似的 sibling

标签 xml xslt xpath

这是我在 StackExchange 上的第一篇文章,如果我做错了什么,请多多包涵:

我有一个从产品数据库派生的 XML 文件,其中除元素顺序外的所有分组信息都丢失了。所有产品都首先有一个商品编号元素,然后是未知数量的其他元素,直到下一个产品以新的商品编号元素开始,如下所示:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Envelope>
    <body>
        <products>
            <ARTNO>10-0001</ARTNO>
            <LEVARTNO>K01-300</LEVARTNO>
            <EAN></EAN>
            <WEBGRUPP1>200</WEBGRUPP1>
            <ARTNO>10C0414</ARTNO>
            <LEVARTNO>0505-0906</LEVARTNO>
            <EAN></EAN>
            <WEBGRUPP1>701</WEBGRUPP1>
            <WEBGRUPP2></WEBGRUPP2>
        </products>
    </body>
</Envelope>

我需要将其重组为:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Envelope>
    <body>
        <products>
            <Product>
                <ARTNO>10-0001</ARTNO>
                <LEVARTNO>K01-300</LEVARTNO>
                <EAN></EAN>
                <WEBGRUPP1>200</WEBGRUPP1>
            </Product>
            <Product>
                <ARTNO>10C0414</ARTNO>
                <LEVARTNO>0505-0906</LEVARTNO>
                <EAN></EAN>
                <WEBGRUPP1>701</WEBGRUPP1>
                <WEBGRUPP2></WEBGRUPP2>
            </Product>
        </products>
    </body>
</Envelope>

我已经尝试了几个小时来找到一个我可以理解的解决方案,但到目前为止还无法做到。我发现一个非常相似的问题得到了回答here但由于我需要匹配除 ARTNO 之外的其他(未知)元素,因此我尝试将其应用于我的案例尚未成功。

我非常简单的 XSL (XSL 1) 基于我的假设,即应该能够让所有后续同级元素到达下一个 ARTNO 元素,但仅此而已(Test 元素只是在尝试时)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1">
    <xsl:output method="xml" indent="yes" encoding="UTF-8" name="xml"/>

    <xsl:template match="/">
        <Root>
            <Products>
                <xsl:for-each select="Envelope/body/products/*">
                    <xsl:apply-templates select="."/>
                </xsl:for-each>
            </Products>
        </Root>
    </xsl:template>


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

    <xsl:template match="ARTNO">
        <Product>
            <xsl:copy-of select="."/>
            <Test>
                <xsl:copy-of select="following-sibling::ARTNO[1]"/>
                <!-- <xsl:value-of select="following-sibling::*[not(self::ARTNO)][2]"/> -->
            </Test>
        </Product>
    </xsl:template>

</xsl:stylesheet>

我想我可以做一些非常丑陋的事情,循环整个结构,并通过使用位置等解决它,但我确信有更好的方法,我希望一些 XSLT 向导可以提供一些指导。我们将不胜感激。

最佳答案

定义一个键<xsl:key name="group" match="products/*[not(self::ARTNO)]" use="generate-id(preceding-sibling::ARTNO[1])"/> ,然后在

中使用它
    <xsl:template match="/">
        <Root>
            <Products>
                    <xsl:apply-templates select="Envelope/body/products/ARTNO"/>
            </Products>
        </Root>
    </xsl:template>

<xsl:template match="ARTNO">
  <Product>
    <xsl:copy-of select=". | key('group', generate-id())"/>
  </Product>
</xsl:template>

关于xml - xsl/xpath 选择最多的 sibling ,但不选择下一个相似的 sibling ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29278297/

相关文章:

php - SimpleXML 能否只加载 XML 的一部分?

Java setURIResolver 没有被调用?

python - 使用 lxml/xpath 解析 html 元素

xml - 亚马逊产品广告 API : How to get a JSON response for ItemLookup/Search

java - 如何在jasper报告中显示导出的xml?

xslt中的java函数getTime

xslt - 可以给我 xsl 中模板 "mode"的示例吗?

xslt - XSLT-使用变量存储属性以在模板中进行匹配

xpath - xpath多重条件并返回根

selenium-webdriver - Selenium:有没有一种方法可以编写xpath来获取包含以数字结尾的文本的元素