【问题标题】:XSLT - convert elements to attributes and include an element from sibling nodeXSLT - 将元素转换为属性并包含来自兄弟节点的元素
【发布时间】:2016-09-29 18:32:35
【问题描述】:

我正在尝试使用 XSLT 转换 XML 文件以实现以下目的:

将节点的所有元素转换为该节点的属性,并在节点内包含节点之外的元素。

为了更清楚一点,我将举一个例子。 我的初始 XML 文件如下所示:

<?xml version="1.0" ?>
<queryResponse type="InventoryDetails" rootUrl="https://10.30.0.192/webacs/api/v1/data"
    requestUrl="https://10.30.0.192/webacs/api/v1/data/InventoryDetails?.full=true&amp;.firstResult=0&amp;.maxResults=1000"
    responseType="listEntityInstances" count="13" first="0" last="12">
    <entity url="https://10.30.0.192/webacs/api/v1/data/InventoryDetails/521521"
        type="InventoryDetails" dtoType="inventoryDetailsDTO">
        <inventoryDetailsDTO id="521521" displayName="521521">
        <deviceId>541541</deviceId>
        <ethernetInterfaces>
             <ethernetInterface>
                    <accessVlan>815</accessVlan>
                    <adminStatus>DOWN</adminStatus>
                    <allowedVlanIds>ALL</allowedVlanIds>
                    <desiredTrunkingEncapsulation>NEGOTIATE_OR_BEING_NEGOTIATED</desiredTrunkingEncapsulation>
                    <desiredVlanMode>ACCESS</desiredVlanMode>
                    <duplexMode>FULLDUPLEX</duplexMode>
                    <macAddress>6c:99:89:45:a4:8d</macAddress>
                    <mtu>1500</mtu>
                    <name>GigabitEthernet1/0/13</name>
                    <nativeVlan>1</nativeVlan>
                    <operationalStatus>DOWN</operationalStatus>
                    <operationalVlanMode>DOWN</operationalVlanMode>
                    <pruneEligibleVlanIds>2-1001</pruneEligibleVlanIds>
                    <speed>
                        <instanceId>0</instanceId>
                        <instanceVersion>0</instanceVersion>
                        <longAmount>1000000000</longAmount>
                    </speed>
                    <trunkingEncapsulationNegotiation>false</trunkingEncapsulationNegotiation>
                </ethernetInterface>
                <ethernetInterface>
                    <accessVlan>1</accessVlan>
                    <adminStatus>UP</adminStatus>
                    <allowedVlanIds>6,11</allowedVlanIds>
                    <desiredTrunkingEncapsulation>_8021Q</desiredTrunkingEncapsulation>
                    <desiredVlanMode>TRUNK</desiredVlanMode>
                    <duplexMode>FULLDUPLEX</duplexMode>
                    <macAddress>6c:99:89:45:a4:92</macAddress>
                    <mtu>1500</mtu>
                    <name>GigabitEthernet1/0/18</name>
                    <nativeVlan>1</nativeVlan>
                    <operationalStatus>UP</operationalStatus>
                    <operationalTrunkEncapsulation>_8021Q</operationalTrunkEncapsulation>
                    <operationalVlanMode>TRUNK</operationalVlanMode>
                    <pruneEligibleVlanIds>2-1001</pruneEligibleVlanIds>
                    <speed>
                        <instanceId>0</instanceId>
                        <instanceVersion>0</instanceVersion>
                        <longAmount>1000000000</longAmount>
                    </speed>
                    <trunkingEncapsulationNegotiation>true</trunkingEncapsulationNegotiation>
                </ethernetInterface>
                <modules>
                <module>
                    <description>Switch 2 - WS-C3750X-48 - Fixed Module 0</description>
                    <equipmentId>546563</equipmentId>
                    <equipmentType>MODULE</equipmentType>
                    <operationStatus>ok</operationStatus>
                    <physicalLocation>WS-C3750X-48</physicalLocation>
                    <productName>Switch 2 - WS-C3750X-48 - Fixed Module 0</productName>
                    <softwareVersion>15.0(2)SE7</softwareVersion>
                    <vendorType>cevModuleCat3750x48</vendorType>
                </module>
                <module>
                    <description>FRULink 10G SM Module</description>
                    <equipmentId>546565</equipmentId>
                    <equipmentType>MODULE</equipmentType>
                    <operationStatus>ok</operationStatus>
                    <physicalLocation>FRULink Container</physicalLocation>
                    <productName>Switch 2 - FRULink Slot 1 - FRULink Module</productName>
                    <softwareVersion>15.0(2)SE7</softwareVersion>
                    <vendorType>cevC3KxSm10g</vendorType>
                </module>
            </modules>
            </ethernetInterfaces>
        </inventoryDetailsDTO>
    </entity>
</queryResponse>

我的结果需要如下:

<Data>
  <ethernetInterface deviceID="xxx" accessVlan="xxxx" adminStatus="xxxx"/>
  <ethernetInterface devideID="xxx" accessVlan="xxxx" adminStatus="xxxx"/>
</Data>

这基本上适用于&lt;entity&gt; 节点内的每个节点和所有属性。 虽然我可以获取一些数据以正确格式化,但我要么得到太多(它只格式化我指定的内容,其余部分仍被复制但未格式化)而且你看到的 DeviceID 不在我得到的节点内属性来自但在一个单独的兄弟节点中。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    尝试以此为起点:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/queryResponse">
        <Data>
            <xsl:for-each select="entity/inventoryDetailsDTO/ethernetInterfaces/ethernetInterface">
                <ethernetInterface deviceID="{../../deviceId}">
                    <xsl:for-each select="accessVlan | adminStatus">
                        <xsl:attribute name="{name()}">
                            <xsl:value-of select="." />
                        </xsl:attribute>
                    </xsl:for-each>
                </ethernetInterface>
            </xsl:for-each>
        </Data>
    </xsl:template>
    
    </xsl:stylesheet>
    

    注意:

    1. XML 区分大小写; deviceID与deviceId不一样;
    2. deviceId 不在“单独的兄弟节点”中;它位于“叔叔”(祖父母的孩子)节点中。正确缩进您的输入 XML 在这里会很有帮助。

    【讨论】:

    • 感谢您的出发点,它实际上几乎正是我所需要的。我将 更改为 所以我可以获得所有属性并像一种魅力。也感谢 Note 的 :) 我认为它是一个兄弟节点,因为它与 >ethernetInterfaces> 并排,我的缩进只是从 notepad++ 给我的内容复制而来的..
    • 作为一个补充问题,如果我想对“模块”做同样的事情但在同一个转换中,我可以复制整个东西并将它放在下面(但仍然在 还是我需要完全调整它?如果我必须完全调整,那么我可能会考虑进行多次转换。(这是因为我有其他可能相似的输出)
    • 我相信你也能做到。最终,为避免代码重复,您可以使用一个模板匹配您希望以相同方式处理的所有节点。
    • 对.. 我可以通过执行 select="template1 | template2" 来做到这一点。伟大的!标记为答案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 2016-12-19
    • 2012-08-30
    相关资源
    最近更新 更多