将XSLT应用于xml文件的简便方法

时间:2012-03-15 20:12:53

标签: xml xslt

我有一个xml文件结构,它有非常神秘的标签(它是HL7 2.3段名称)。

我知道所有标签在普通英语中的含义。但每次我必须阅读文件时查找它们都很痛苦。

据我了解,我可以创建一个XSLT,它允许我以易于阅读的方式查看我的xml文件。

一旦我创建了这个XSLT,是否有一种非常快速简便的方法将它应用到我的xml文档中(即从SQL或MSMQ复制并粘贴它并将其自动格式化为XSLT定义?

(注意:XML文件包含我无法以任何方式加载到Web上的数据。因此任何公共托管的Web解决方案都不起作用。)

Bounty更新:
为Maestro13的答案添加了一笔赏金,以便在父级和当前节点上进行匹配。 (而不仅仅是当前节点。)

因为这首先是Maestro13的答案,所以我会将奖励给予其他类似的答案。

4 个答案:

答案 0 :(得分:3)

如果您正好在unix上,那么xsltproc(来自libxslt包):

xsltproc your.xsl your.xml

答案 1 :(得分:2)

我在下面为你写了一个小例子。

要运行它,您需要一个像XML Spy,Oxygen这样的工具,或者安装Java JDK和Saxon 9HE,并按照Alp的说明从命令行运行它。不确定如何在Saxon调用或XSLT本身中指定转换文件,但请参阅Saxon command line syntax;在Oxygen或XML Spy中,这是在参数列表弹出窗口中完成的。

输入文件(不是一个真实的例子,只是类似HL7的XML的摘录):

<?xml version="1.0" encoding="UTF-8"?>
<ADT_A03>
    <MSH>
        <MSH.7>19900314130405</MSH.7>
    </MSH>
    <EVN>
        <EVN.6>19980327095000</EVN.6>
    </EVN>
    <PID>
        <PID.4.LST>
            <PID.4>
                <CX.1>123456789ABCDEF</CX.1>
            </PID.4>
        </PID.4.LST>
        <PID.5.LST>
            <PID.5>
                <XPN.1>PATIENT</XPN.1>
                <XPN.2>BOB</XPN.2>
                <XPN.3>S</XPN.3>
            </PID.5>
        </PID.5.LST>
    </PID>
</ADT_A03>

包含HL7标签翻译的附加XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<HL7_translations>
    <MSH description="MessageHeader">
        <MSH.7 description="DateTimeOfMessage"/>
    </MSH>
    <EVN description="EventType">
        <EVN.6 description="EventOccurred"/>
    </EVN>
    <PID description="PatientIdentification">
        <PID.1 description="SetID_PatientID"/>
        <PID.2 description="PatientID_ExternalID"/>
        <PID.3 description="PatientID_InternalID"/>
        <PID.4 description="AlternatePatientID_PID"/>
        <PID.5 description="PatientName"/>
    </PID>
</HL7_translations>

XSL转换,读取和处理两个文件(param是转换文件;输入源文件是HL7 XML):

<?xml version="1.0" encoding="UTF-8"?>
<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:param name="HL7_translations"/>

<xsl:variable name="doc" select="document($HL7_translations)"/>

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

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

<xsl:template match="*">
    <xsl:variable name="trans" select="$doc//*[name() = name(current())]/@description"/>
    <xsl:copy>
        <xsl:if test="$trans">
            <xsl:attribute name="description"><xsl:value-of select="$trans"/></xsl:attribute>
        </xsl:if>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

输出结果:

<?xml version="1.0" encoding="UTF-8"?>
<ADT_A03>
    <MSH description="MessageHeader">
        <MSH.7 description="DateTimeOfMessage">19900314130405</MSH.7>
    </MSH>
    <EVN description="EventType">
        <EVN.6 description="EventOccurred">19980327095000</EVN.6>
    </EVN>
    <PID description="PatientIdentification">
        <PID.4.LST>
            <PID.4 description="AlternatePatientID_PID">
                <CX.1>123456789ABCDEF</CX.1>
            </PID.4>
        </PID.4.LST>
        <PID.5.LST>
            <PID.5 description="PatientName">
                <XPN.1>PATIENT</XPN.1>
                <XPN.2>BOB</XPN.2>
                <XPN.3>S</XPN.3>
            </PID.5>
        </PID.5.LST>
    </PID>
</ADT_A03>

编辑以在检索说明时包含父节点

新的XML输入

<?xml version="1.0" encoding="UTF-8"?>
<ADT_A03>
    <MSH>
        <MSH.7>19900314130405</MSH.7>
    </MSH>
    <EVN>
        <EVN.6>19980327095000</EVN.6>
    </EVN>
    <PID>
        <PID.4.LST>
            <PID.4>
                <CX.1>123456789ABCDEF</CX.1>
            </PID.4>
        </PID.4.LST>
        <PID.5.LST>
            <PID.5>
                <XPN.1>PATIENT</XPN.1>
                <XPN.2>BOB</XPN.2>
                <XPN.3>S</XPN.3>
            </PID.5>
        </PID.5.LST>
    </PID>
    <PV1>
        <PV1.7>
            <XCN.1>Attending Doctor's name</XCN.1>
        </PV1.7>
        <PV1.8>
            <XCN.1>Referring Doctor's name</XCN.1>
        </PV1.8>
    </PV1>
    <OBR>
        <OBR.10>
            <XCN.1>Collector Identifier's name</XCN.1>
        </OBR.10>
    </OBR>
</ADT_A03>

带有描述的新文件(注意添加像PID.4.LST这样的中间级别!)

<?xml version="1.0" encoding="UTF-8"?>
<HL7_translations>
    <MSH description="MessageHeader">
        <MSH.7 description="DateTimeOfMessage"/>
    </MSH>
    <EVN description="EventType">
        <EVN.6 description="EventOccurred"/>
    </EVN>
    <PID description="PatientIdentification">
        <PID.1 description="SetID_PatientID"/>
        <PID.2 description="PatientID_ExternalID"/>
        <PID.3 description="PatientID_InternalID"/>
        <PID.4.LST>
            <PID.4 description="AlternatePatientID_PID"/>
        </PID.4.LST>
        <PID.5.LST>
            <PID.5 description="PatientName"/>
        </PID.5.LST>
    </PID>
    <PV1>
        <PV1.7>
            <XCN.1 description="Attending Doctor"/>
        </PV1.7>
        <PV1.8>
            <XCN.1 description="Referring Doctor"/>
        </PV1.8>
    </PV1>
    <OBR>
        <OBR.10>
            <XCN.1 description="Collector Identifier"/>
        </OBR.10>
    </OBR>
</HL7_translations>

新xslt

<?xml version="1.0" encoding="UTF-8"?>
<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:param name="HL7_translations"/>

<xsl:variable name="doc" select="document($HL7_translations)"/>

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

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

<xsl:template match="*">
    <xsl:variable name="trans" select="$doc//*[ name() = name(current()) and 
        ( name(current()/..) = name(..) or name(..) = 'HL7_translations')
        ]"/>
    <xsl:copy>
        <xsl:if test="$trans/@description">
            <xsl:attribute name="description"><xsl:value-of select="$trans/@description"/></xsl:attribute>
        </xsl:if>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

所以唯一的变化是

<xsl:variable name="trans" select="$doc//*[ name() = name(current()) and 
    ( name(current()/..) = name(..) or name(..) = 'HL7_translations')
    ]"/>

加上我将/ @描述移出变量。

新的输出结果

<?xml version="1.0" encoding="UTF-8"?>
<ADT_A03>
    <MSH description="MessageHeader">
        <MSH.7 description="DateTimeOfMessage">19900314130405</MSH.7>
    </MSH>
    <EVN description="EventType">
        <EVN.6 description="EventOccurred">19980327095000</EVN.6>
    </EVN>
    <PID description="PatientIdentification">
        <PID.4.LST>
            <PID.4 description="AlternatePatientID_PID">
                <CX.1>123456789ABCDEF</CX.1>
            </PID.4>
        </PID.4.LST>
        <PID.5.LST>
            <PID.5 description="PatientName">
                <XPN.1>PATIENT</XPN.1>
                <XPN.2>BOB</XPN.2>
                <XPN.3>S</XPN.3>
            </PID.5>
        </PID.5.LST>
    </PID>
    <PV1>
        <PV1.7>
            <XCN.1 description="Attending Doctor">Attending Doctor's name</XCN.1>
        </PV1.7>
        <PV1.8>
            <XCN.1 description="Referring Doctor">Referring Doctor's name</XCN.1>
        </PV1.8>
    </PV1>
    <OBR>
        <OBR.10>
            <XCN.1 description="Collector Identifier">Collector Identifier's name</XCN.1>
        </OBR.10>
    </OBR>
</ADT_A03>

答案 2 :(得分:1)

您可以使用Saxon's XSLT processor执行此操作。

java -jar saxon9he.jar -xsl:your_transformation_file.xsl -s:your_source_input.xml -o:your_transformed_output.xml

答案 3 :(得分:1)

包含父节点名称的描述检索的单独答案(为方便起见)

新的XML输入

<?xml version="1.0" encoding="UTF-8"?>
<ADT_A03>
    <MSH>
        <MSH.7>19900314130405</MSH.7>
    </MSH>
    <EVN>
        <EVN.6>19980327095000</EVN.6>
    </EVN>
    <PID>
        <PID.4.LST>
            <PID.4>
                <CX.1>123456789ABCDEF</CX.1>
            </PID.4>
        </PID.4.LST>
        <PID.5.LST>
            <PID.5>
                <XPN.1>PATIENT</XPN.1>
                <XPN.2>BOB</XPN.2>
                <XPN.3>S</XPN.3>
            </PID.5>
        </PID.5.LST>
    </PID>
    <PV1>
        <PV1.7>
            <XCN.1>Attending Doctor's name</XCN.1>
        </PV1.7>
        <PV1.8>
            <XCN.1>Referring Doctor's name</XCN.1>
        </PV1.8>
    </PV1>
    <OBR>
        <OBR.10>
            <XCN.1>Collector Identifier's name</XCN.1>
        </OBR.10>
    </OBR>
</ADT_A03>

带有描述的新文件(注意添加像PID.4.LST这样的中间级别!)

<?xml version="1.0" encoding="UTF-8"?>
<HL7_translations>
    <MSH description="MessageHeader">
        <MSH.7 description="DateTimeOfMessage"/>
    </MSH>
    <EVN description="EventType">
        <EVN.6 description="EventOccurred"/>
    </EVN>
    <PID description="PatientIdentification">
        <PID.1 description="SetID_PatientID"/>
        <PID.2 description="PatientID_ExternalID"/>
        <PID.3 description="PatientID_InternalID"/>
        <PID.4.LST>
            <PID.4 description="AlternatePatientID_PID"/>
        </PID.4.LST>
        <PID.5.LST>
            <PID.5 description="PatientName"/>
        </PID.5.LST>
    </PID>
    <PV1>
        <PV1.7>
            <XCN.1 description="Attending Doctor"/>
        </PV1.7>
        <PV1.8>
            <XCN.1 description="Referring Doctor"/>
        </PV1.8>
    </PV1>
    <OBR>
        <OBR.10>
            <XCN.1 description="Collector Identifier"/>
        </OBR.10>
    </OBR>
</HL7_translations>

新xslt

<?xml version="1.0" encoding="UTF-8"?>
<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:param name="HL7_translations"/>

<xsl:variable name="doc" select="document($HL7_translations)"/>

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

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

<xsl:template match="*">
    <xsl:variable name="trans" select="$doc//*[ name() = name(current()) and 
        ( name(current()/..) = name(..) or .. = .//*[1])
        ]"/>
    <xsl:copy>
        <xsl:if test="$trans/@description">
            <xsl:attribute name="description"><xsl:value-of select="$trans/@description"/></xsl:attribute>
        </xsl:if>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

所以唯一的变化是

<xsl:variable name="trans" select="$doc//*[ name() = name(current()) and 
    ( name(current()/..) = name(..) or .. = .//*[1])
    ]"/>

加上我将/ @描述移出变量。

新的输出结果

<?xml version="1.0" encoding="UTF-8"?>
<ADT_A03>
    <MSH description="MessageHeader">
        <MSH.7 description="DateTimeOfMessage">19900314130405</MSH.7>
    </MSH>
    <EVN description="EventType">
        <EVN.6 description="EventOccurred">19980327095000</EVN.6>
    </EVN>
    <PID description="PatientIdentification">
        <PID.4.LST>
            <PID.4 description="AlternatePatientID_PID">
                <CX.1>123456789ABCDEF</CX.1>
            </PID.4>
        </PID.4.LST>
        <PID.5.LST>
            <PID.5 description="PatientName">
                <XPN.1>PATIENT</XPN.1>
                <XPN.2>BOB</XPN.2>
                <XPN.3>S</XPN.3>
            </PID.5>
        </PID.5.LST>
    </PID>
    <PV1>
        <PV1.7>
            <XCN.1 description="Attending Doctor">Attending Doctor's name</XCN.1>
        </PV1.7>
        <PV1.8>
            <XCN.1 description="Referring Doctor">Referring Doctor's name</XCN.1>
        </PV1.8>
    </PV1>
    <OBR>
        <OBR.10>
            <XCN.1 description="Collector Identifier">Collector Identifier's name</XCN.1>
        </OBR.10>
    </OBR>
</ADT_A03>